纯C实现单链表相邻节点交换 无需双指针修复冒泡排序节点丢失问题
问题修复说明
核心错误点
- 内存分配错误:
createListWithHead函数中申请list结构体内存时,错误使用sizeof(ptrList)(获取的是指针变量的大小),应改为sizeof(list),否则会出现内存越界导致未定义行为。 - 节点交换逻辑缺陷:
swapListNodeWithNext仅修改了两个待交换节点的next指针,没有修改两个节点的前驱节点的next指向。除头节点交换外,其余位置交换时前驱节点仍指向原来的第一个节点,直接导致第二个待交换节点从链表中丢失,这就是你节点7消失的原因。同时C语言是值传递,函数内部对形参ptrToListNode1的赋值无法影响外部实参,这行代码完全无效。 - 排序循环逻辑缺陷:交换节点后没有正确更新当前遍历指针的位置,会导致遍历顺序错误。
最简修复方案(无需双指针,无节点交换逻辑)
你完全不需要交换链表节点本身,冒泡排序仅交换两个节点的data值即可实现排序,逻辑简单,完全不会出现指针操作失误导致的节点丢失问题,修改如下:
- 删掉原来的
swapListNodeWithNext函数 - 修复
createListWithHead的内存分配和野指针问题:
list *createListWithHeadData(int data) { list *ptrList = malloc(sizeof(list)); // 修正内存分配大小 listNode *ptrNewNode = malloc(sizeof(listNode)); ptrNewNode->data = data; ptrNewNode->next = NULL; // 新增初始化next为NULL,避免野指针 ptrList->head = ptrNewNode; ptrList->tail = ptrNewNode; return ptrList; }
- 修改
sortList函数逻辑,直接交换节点的data值:
void sortList(list *ptrToListToSort) { if (ptrToListToSort->head == NULL || ptrToListToSort->head->next == NULL) { return; } int swapped; listNode *ptr1; listNode *lptr = NULL; do { swapped = 0; ptr1 = ptrToListToSort->head; while (ptr1->next != lptr) { if (ptr1->data > ptr1->next->data) { // 直接交换节点数据,无需修改指针 int temp = ptr1->data; ptr1->data = ptr1->next->data; ptr1->next->data = temp; swapped = 1; } ptr1 = ptr1->next; } lptr = ptr1; } while (swapped); // 同步更新尾指针 listNode *t = ptrToListToSort->head; while(t->next) t = t->next; ptrToListToSort->tail = t; }
修改后运行即可得到正确的升序排序结果。
如果你一定要交换节点
如果业务要求必须交换节点本身而非节点值,那么你必须记录当前节点的前驱节点:
- 单链表的每个节点只有指向后继的指针,没有指向前驱的指针,要修改前驱的next指向,就必须提前保存前驱节点的地址,这就是你提到的"双指针"的作用:一个指针指向当前节点,另一个指向当前节点的前驱节点。
- 交换两个节点A和B(前驱是pre)的逻辑为:
pre->next = B; A->next = B->next; B->next = A; - 如果A是头节点,直接更新链表的head为B即可。
内容的提问来源于stack exchange,提问作者DragonAngel the Original
相关产品推荐
相关产品推荐

