【发布时间】:2015-08-30 16:55:55
【问题描述】:
我正在做一个练习题以提高我的 C。这是问题:
编写一个函数对整数链表进行排序,如下所示:
a) 找出列表中的最大值。
b) 将其从其位置删除并插入到列表的头部。
c) 从现在的第二个元素开始,重复 (a) 和 (b)。
d) 从现在的第三个元素开始,重复 (a) 和 (b)。
继续直到列表排序。
我的排序功能:
NodePtr sortList(NodePtr np) {
NodePtr makeNode(int), head, temp;
head = temp = np;
if (np != NULL) {
// Determine linked list length
int len = 0;
while (temp != NULL) {
len++;
temp = temp -> next;
}
int i;
for (i = 0; i < len; i++) {
temp = head;
int j;
// Traverse to spot j in linked list
for (j = 0; j < i; j++) {
temp = temp -> next;
}
// Find largest
NodePtr largest, prev, prevToLargest;
largest = prev = prevToLargest = temp;
while (temp != NULL) {
if (temp -> num > largest -> num) {
largest = temp;
prevToLargest = prev;
}
if (temp != prev) prev = prev -> next;
temp = temp -> next;
}
prevToLargest -> next = largest -> next;
largest -> next = head;
head = largest;
}
}
return head;
}
使用调试器我发现我的列表已排序但它是无限的。我相信我已经创建了一个循环链表,但我不知道如何解决这个问题。
感谢您的帮助!
【问题讨论】:
-
请不要在
->前后放置空格。这使您的代码难以阅读,并且几乎在所有地方都不鼓励使用。 -
所有以注释开头的代码部分都可以(应该?)被提取到它们自己的函数中。这将使调试(和编写单元测试)变得更加容易......
-
如果列表是空终止的,为什么还要预先计算列表?您应该能够使用终止 null 来中断 for() 或 while() 循环进行排序而无需预先计数。如果没有别的,通过在列表中添加一个额外的不必要的循环,这是非最优的低效代码。
-
评论说“遍历以在列表中发现
j”,但您实际上是在遍历以在列表中发现i并将该位置保存在j中。正确命名并准确指定问题非常重要,否则您会遇到维护问题。另外,@idmean 是绝对正确的,不要在->周围加空格@ -
这大约是基本 O(N^2) 链表排序所需代码的 3 倍。单个指针对指针消除了 ton (see it live here)。除非有 非常 特定条件,否则应避免使用hiding pointer types in
typedefaliases。拥抱你的 C 再现并拥抱一个星号。
标签: c linked-list