正如其他人所说,没有反向链接就无法在链表中“备份”。虽然这不完全是您问题的答案,但可以通过三个队列轻松完成排序,实现具有三个存储桶的存储桶排序。
队列(堆上的副推)的优点是排序是稳定的。也就是说,如果列表节点中有数据(除了 0、1、2 值的键),每个键的这些数据将保持相同的顺序。
这只是数组的规范算法不适用于列表的众多情况之一。
有一种非常巧妙、简单的方法来实现队列:循环链表,其中第一个节点,比如p
,是队列的尾部,因此p->next
是头部。这样,代码就很简洁了。
#include <stdio.h>
#include <stdlib.h>
typedef struct node_s {
struct node_s *next;
int val;
int data;
} NODE;
// Add node to tail of queue q and return the new queue.
NODE *enqueue(NODE *q, NODE *node)
{
if (q) {
node->next = q->next;
q->next = node;
}
else node->next = node;
return node;
}
// Concatenate qa and qb and return the result.
NODE *cat(NODE *qa, NODE *qb)
{
NODE *head = qa->next;
qa->next = qb->next;
qb->next = head;
return qb;
}
// Sort a list where all values are 0, 1, or 2.
NODE *sort012(NODE *list)
{
NODE *next = NULL, *q[3] = { NULL, NULL, NULL};
for (NODE *p = list; p; p = next) {
next = p->next;
q[p->val] = enqueue(q[p->val], p);
}
NODE *result = cat(q[0], cat(q[1], q[2]));
// Now transform the circular queue to a simple linked list.
NODE *head = result->next;
result->next = NULL;
return head;
}
int main(void)
{
NODE *list = NULL;
int N = 100;
// Build a list of nodes for testing
for (int i = 0; i < N; ++i) {
NODE *p = malloc(sizeof(NODE));
p->val = rand() % 3;
p->data = N - i; // List ends up with data 1,2,3,..,N
p->next = list;
list = p;
}
list = sort012(list);
for (NODE *p = list; p; p = p->next)
printf("key val=%d, data=%d\n", p->val, p->data);
return 0;
}
现在这是一个完整的简单测试,并且运行良好。
这是未经测试的。(如果我有时间,我会尝试测试它。)但它至少应该非常接近解决方案。