简体   繁体   English

在C ++中对整数的链表进行排序

[英]Sorting a linked-list of ints in C++

I have to make a type of linked-list that stores ints in order from smallest to largest. 我必须创建一种从最小到最大顺序存储整数的链接列表。 If you have or know how to make a sorting function for linked-lists please show if off here and / or teach me how to code it in C++. 如果您具有或知道如何对链表进行排序,请在此处显示是否关闭和/或教我如何使用C ++进行编码。

I often sort linked lists via an index-pointer-list. 我经常通过索引指针列表对链接列表进行排序。 To build one requires a memory allocation equivalent to the number of nodes (N) * the size of a node pointer. 要构建一个,需要的内存分配等于节点数(N)*节点指针的大小。 The concept is simple enough. 这个概念很简单。

Note: this algorithm is in C, as I was not entirely sure if the OP meant to class this as a C++ question (who the hell uses linked lists in C++ with the standard containers at your disposal??) 注:该算法是C,因为我不能完全肯定是否意味着这个类作为一个C ++的问题( 到底谁在使用您的处置??链接在C列出++与标准集装箱)的OP

  1. Determine the number (N) of nodes in the list 确定列表中的节点数(N)
  2. Allocate a pointer-array for N node pointers . 为N个节点指针分配一个指针数组。
  3. Load the pointer array with every node pointer in the list. 使用列表中的每个节点指针加载指针数组。 Ie walk the list, and put a pointer in each slot of the pointer-array, incrementing as you go. 即遍历列表,然后将指针放在指针数组的每个插槽中,并随您的增加而递增。
  4. Send this node pointer array to your sorting algorithm (I like the runtime library qsort() since it is standard-equipped). 将此节点指针数组发送到您的排序算法(我喜欢运行时库qsort()因为它是标准配备的)。
  5. After sorting, walk the entire pointer array (less one), setting each node's "next" pointer to point to the one that follows. 排序后,遍历整个指针数组(少一个),将每个节点的“下一个”指针设置为指向后面的指针。 The last one sets its "next" pointer to NULL. 最后一个将其“下一个”指针设置为NULL。
  6. Set the head pointer to be the first pointer [0] in the pointer array. 将头指针设置为指针数组中的第一个指针[0]。
  7. Free the memory of the pointer array 释放指针数组的内存

Your linked list is sorted. 您的链接列表已排序。


Assuming your node is something like this: 假设您的节点是这样的:

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

Determine the number of nodes in your list. 确定列表中的节点数。 I'm assuming you have a proc that can do this, which is trivial: 我假设您有一个可以执行此操作的proc,这很简单:

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

Allocate a pointer array the size of the list, where nItems is the list node count greater than 1 (no sense in bothering with a list of length zero or one): 分配一个列表大小的指针数组,其中nItems是列表节点计数大于1的列表(烦扰长度为零或一的列表是没有意义的):

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

Populate the pointer array with all the items in the list: 用列表中的所有项目填充指针数组:

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

Now send this to qsort() with an appropriate comparision function. 现在,使用适当的比较函数将其发送到qsort() An example comparison function that sorts based on the keyField in our structure is below: 下面是一个根据我们结构中的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;
}

Invoking qsort() looks like this: 调用qsort()如下所示:

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

Now walk the entire list. 现在遍历整个列表。 rewiring "next" pointers: 重新连接“下一个”指针:

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

Rewire the head pointer. 重新连接头指针。

head = ptrs[0];

And finally, free the pointer array. 最后,释放指针数组。

free(ptrs);

Your linked list is sorted. 您的链接列表已排序。


Sidebar merge-sort is the only O(nlogn) algorithm I know of that can sort a linked list with no added space requirements. 边栏合并排序是我所知道的唯一O(nlogn)算法,可以对链表进行排序,而无需增加空间。 A general solution that prototypes to the following would be nutz: 可以原型为以下内容的通用解决方案是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.

If we simply show you the code we will be doing you a great disservice. 如果仅向您显示代码,我们将对您造成极大的伤害。 I will give you, instead, two different approaches and you can implement the one that you prefer. 相反,我将为您提供两种不同的方法,您可以实施自己喜欢的一种方法。

The first approach is to "sort" as you insert: when you are inserting a value, say, 7, you follow this procedure starting with the first entry in your list until you run out of nodes: 第一种方法是在插入时进行“排序”:在插入值(例如7)时,请按照以下过程从列表中的第一个条目开始,直到用尽节点:

If the node you are examining has a value that is greater than 7 you insert a new node before the node you are examining and return. 如果要检查的节点的值大于7,则在要检查的节点之前插入一个新节点并返回。 Otherwise you look at the next node. 否则,您将查看下一个节点。 If there is no next node, the. 如果没有下一个节点,则。 You insert a new node at the end of the list since that means that 7 is larger than al other entries in the list and return. 您在列表末尾插入一个新节点,因为这意味着7比列表中的其他条目大,然后返回。

A second alternative is to sort the entire list using one of the many sorting algorithms. 第二种选择是使用许多排序算法之一对整个列表进行排序。 I would suggest that you use BubbleSort since it's easy to understand and implement. 我建议您使用BubbleSort,因为它易于理解和实施。 You can read more about bubblesort (ans many other sorting algorithms) on Wikipedia. 您可以在Wikipedia上阅读有关Bubblesort(其他许多排序算法)的更多信息。

Good old quicksort will do the trick (C++03 friendly): 好的旧的quicksort可以解决问题(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;
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM