-1

我必须创建一种以从最小到最大的顺序存储整数的链表。如果您有或知道如何为链表创建排序功能,请在此处显示是否关闭和/或教我如何用 C++ 编写代码。

4

3 回答 3

3

我经常通过索引指针列表对链表进行排序。要构建一个,需要分配相当于节点数 (N) * 节点指针大小的内存。这个概念很简单。

注意:这个算法在 C 中,因为我不完全确定 OP 是否打算将其归类为 C++ 问题(谁在 C ++中使用链表和标准容器供您使用??)

  1. 确定列表中的节点数(N)
  2. 为 N 节点指针分配一个指针数组。
  3. 使用列表中的每个节点指针加载指针数组。即遍历列表,并在指针数组的每个插槽中放置一个指针,随着您的进行递增。
  4. 将此节点指针数组发送到您的排序算法(我喜欢运行时库qsort(),因为它是标准配备的)。
  5. 排序后,遍历整个指针数组(少一个),设置每个节点的“下一个”指针指向后面的那个。最后一个将其“下一个”指针设置为 NULL。
  6. 将头指针设置为指针数组中的第一个指针[0]。
  7. 释放指针数组的内存

您的链接列表已排序。


假设您的节点是这样的:

struct node
{
   ..data fields..
   int keyField;  // << determines sort order
   struct node *next;
};

确定列表中的节点数。我假设你有一个可以做到这一点的 proc,这很简单:

size_t list_count(struct node* head)
{
   size_t count = 0;
   while (head)
   {
      ++count;
      head = head->next;
   }
   return count;
}

分配一个列表大小的指针数组,其中 nItems 是大于 1 的列表节点计数(与长度为 0 或 1 的列表无关):

struct node **ptrs = malloc(sizeof(*ptrs)*nItems);

用列表中的所有项目填充指针数组:

struct node *ptr = head;
size_t i=0;
for (;i<nItems;++i,ptr = ptr->next)
    ptrs[i] = ptr;

现在qsort()使用适当的比较功能将其发送到。下面是一个基于keyField我们结构中的排序的示例比较函数:

int compare_node_ptrs(const void* left, const void* right)
{
    struct node *l = *(struct node**)left;
    struct node *r = *(struct node**)right;
    return l->keyField - r->keyField;
}

调用 qsort() 看起来像这样:

qsort(ptrs, nItems, sizeof(*ptrs), compare_node_ptrs);

现在遍历整个列表。重新布线“下一个”指针:

for (i=0;i<(nItems-2);++i)
    ptrs[i]->next = ptrs[i+1];
ptrs[nItems-1] = NULL;

重新连接头指针。

head = ptrs[0];

最后,释放指针数组。

free(ptrs);

您的链接列表已排序。


侧边栏合并排序是我所知道的唯一一种 O(nlogn) 算法,它可以对链表进行排序而无需增加空间要求。以下原型的通用解决方案将是 nutz:

mergesort_list(void **head, size_t offset_ptr, int(*comp)(void*,void*))

head: address of the head pointer.
offset_ptr: offset in bytes from a node ptr where the 'link' pointer can be found.
comp: comparison function.
于 2012-11-15T23:36:14.847 回答
2

如果我们只是向您展示代码,我们将对您造成极大的伤害。相反,我会给你两种不同的方法,你可以实现你喜欢的一种。

第一种方法是在插入时进行“排序”:当您插入一个值(例如 7)时,您按照此过程从列表中的第一个条目开始,直到用完节点:

如果您正在检查的节点的值大于 7,则在您正在检查的节点之前插入一个新节点并返回。否则,您将查看下一个节点。如果没有下一个节点,则。您在列表末尾插入一个新节点,因为这意味着 7 大于列表中的所有其他条目并返回。

第二种选择是使用许多排序算法之一对整个列表进行排序。我建议您使用 BubbleSort,因为它易于理解和实现。您可以在 Wikipedia 上阅读有关冒泡排序(以及许多其他排序算法)的更多信息。

于 2012-11-15T23:23:47.523 回答
1

好的旧快速排序可以解决问题(C++03 友好):

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>

using namespace std;

void qsort(list<int>::iterator first, list<int>::iterator last)
{
    if (distance(first, last) < 2)
        return;
    int pivot = *first;

    list<int>::iterator it = partition(first, last, bind2nd(less<int>(), pivot));

    qsort(first, it);
    qsort(it, last);
}

int main()
{
    std::list<int> l;
    l.push_back(5);
    l.push_back(4);
    l.push_back(1);
    l.push_back(10);
    l.push_back(3);
    l.push_back(6);
    l.push_back(7);

    cout << "List:";
    copy(l.begin(), l.end(), std::ostream_iterator<int>(std::cout, " "));
    cout << endl;

    qsort(l.begin(), l.end());

    cout << "Sorted list:";
    copy(l.begin(), l.end(), std::ostream_iterator<int>(std::cout, " "));
    cout << endl;
    return 0;
}

检查:http: //ideone.com/OOGXSp

于 2012-11-15T23:40:47.613 回答