C语言链表冒泡排序函数异常:结果错误或无限循环,求查循环问题
分析你的链表冒泡排序循环问题
首先,你的代码里有几个关键逻辑错误,直接导致了排序结果错误和无限循环的问题,我来逐一拆解:
1. 边界条件处理缺失
你的代码一开始直接访问h->next和p1->next,如果链表是空的(只有头节点)或者只有一个元素,这里会触发空指针访问,直接引发崩溃或未定义行为。而且外层循环的条件while (p2->next != NULL)完全不符合冒泡排序的终止逻辑,会漏掉最后一个元素的比较,还会在指针移动后出现异常。
2. 冒泡排序的循环结构完全错误
标准链表冒泡排序的核心是每一轮从链表头部开始比较,把当前最大的元素“沉”到末尾,但你的代码每轮结束后把p1、p2、opp都往后移,相当于每轮只处理链表的后半段,这完全违背了冒泡排序的逻辑,必然会导致排序不完整,甚至指针越界进入死循环。
3. 节点交换后的指针更新错误
当你交换p1和p2之后,执行p1 = p1->next是错误的——交换后p1已经被放到p2的后面,此时直接移动p1会跳过下一个需要比较的元素,导致指针链混乱,进而引发死循环或者排序错误。
修正后的代码
我重新编写了符合冒泡排序逻辑的链表排序函数,你可以参考:
#include <stdio.h> typedef struct Node { int score; struct Node *next; } Node; void Sort_list(Node *h) { // 边界条件:链表为空或元素不足2个,直接返回 if (h == NULL || h->next == NULL || h->next->next == NULL) { return; } int swapped; Node *last_sorted = NULL; // 标记上一轮已排好序的节点,后续无需再比较 Node *prev = h; Node *curr; Node *next_node; do { swapped = 0; prev = h; curr = h->next; next_node = curr->next; // 每一轮比较到last_sorted之前的节点 while (next_node != last_sorted) { if (curr->score > next_node->score) { // 交换curr和next_node节点 curr->next = next_node->next; next_node->next = curr; prev->next = next_node; // 更新指针,继续下一次比较 swapped = 1; prev = next_node; // 交换后prev指向next_node next_node = curr->next; // next_node移到curr的下一个 } else { // 无需交换,直接移动指针 prev = curr; curr = next_node; next_node = next_node->next; } } last_sorted = curr; // 本轮结束后,curr是最后一个已排好序的节点 } while (swapped); // 若某一轮无交换,说明链表已有序,直接退出 }
代码说明
- 边界条件检查:提前判断链表是否为空或元素不足,避免空指针访问。
- 排序终止标志:用
swapped标记每一轮是否发生交换,无交换则说明链表已有序,直接退出,避免无用循环。 - 正确的循环逻辑:每一轮从链表头部开始比较,直到上一轮排好序的节点前,保证每轮都能把当前最大元素沉到末尾。
- 交换后指针更新:交换节点后正确调整
prev、curr、next_node的指向,避免指针链混乱。
你可以替换原有函数,测试不同长度的链表,应该就能解决结果错误和无限循环的问题了。
内容的提问来源于stack exchange,提问作者stark Jhon
相关产品推荐
相关产品推荐

