我必须创建一种以从最小到最大的顺序存储整数的链表。如果您有或知道如何为链表创建排序功能,请在此处显示是否关闭和/或教我如何用 C++ 编写代码。
3 回答
我经常通过索引指针列表对链表进行排序。要构建一个,需要分配相当于节点数 (N) * 节点指针大小的内存。这个概念很简单。
注意:这个算法在 C 中,因为我不完全确定 OP 是否打算将其归类为 C++ 问题(谁在 C ++中使用链表和标准容器供您使用??)
- 确定列表中的节点数(N)
- 为 N 节点指针分配一个指针数组。
- 使用列表中的每个节点指针加载指针数组。即遍历列表,并在指针数组的每个插槽中放置一个指针,随着您的进行递增。
- 将此节点指针数组发送到您的排序算法(我喜欢运行时库
qsort()
,因为它是标准配备的)。 - 排序后,遍历整个指针数组(少一个),设置每个节点的“下一个”指针指向后面的那个。最后一个将其“下一个”指针设置为 NULL。
- 将头指针设置为指针数组中的第一个指针[0]。
- 释放指针数组的内存
您的链接列表已排序。
假设您的节点是这样的:
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.
如果我们只是向您展示代码,我们将对您造成极大的伤害。相反,我会给你两种不同的方法,你可以实现你喜欢的一种。
第一种方法是在插入时进行“排序”:当您插入一个值(例如 7)时,您按照此过程从列表中的第一个条目开始,直到用完节点:
如果您正在检查的节点的值大于 7,则在您正在检查的节点之前插入一个新节点并返回。否则,您将查看下一个节点。如果没有下一个节点,则。您在列表末尾插入一个新节点,因为这意味着 7 大于列表中的所有其他条目并返回。
第二种选择是使用许多排序算法之一对整个列表进行排序。我建议您使用 BubbleSort,因为它易于理解和实现。您可以在 Wikipedia 上阅读有关冒泡排序(以及许多其他排序算法)的更多信息。
好的旧快速排序可以解决问题(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