C语言双向链表打印异常:仅最后一个元素输出正确问题排查
错误根因
你的代码存在两处核心问题:
add函数遍历找尾节点的循环中,多余执行了before->previous=before;操作,直接把每个遍历到的节点的前驱指针指向了自身,这就是你打印时previous字段和当前节点值一致的直接原因。双向链表尾部加节点的逻辑不需要修改原有节点的前驱指针,这行代码完全多余。main函数的遍历逻辑终止条件设为head->next,会直接跳过最后一个节点(next值为NULL)不会打印,同时直接修改head指针会丢失链表头地址,后续无法再从头部访问整个链表。
修正后的代码
add函数修正版
// 提前定义listw结构体,你本地已有的话可以忽略 typedef struct listw { int number; struct listw* previous; struct listw* next; } listw; listw* add(listw* head, int number) { listw* before = head; // 仅遍历找尾节点,不要修改原有节点的指针 if (head) while (before->next) before = before->next; // 不要用new作为变量名,避免和C++关键字冲突 listw* new_node = calloc(1, sizeof(listw)); new_node->number = number; new_node->next = NULL; if (before) { before->next = new_node; new_node->previous = before; } return head ? head : new_node; }
打印逻辑修正版
#include <stdio.h> #include <stdlib.h> int main(){ listw* head = add(NULL, 7); head = add(head, 12); head = add(head, 18); head = add(head, 20); // 用临时指针遍历,不修改原head指针 listw* cur = head; while (cur != NULL) { if (cur->previous == NULL) { // 头节点处理 if (cur->next) printf("previous: none, now: %d, next: %d\n", cur->number, cur->next->number); else printf("previous: none, now: %d, next: none\n", cur->number); } else if (cur->next == NULL) { // 尾节点处理 printf("previous: %d, now: %d, next: none\n", cur->previous->number, cur->number); } else { // 中间节点处理 printf("previous: %d, now: %d, next: %d\n", cur->previous->number, cur->number, cur->next->number); } cur = cur->next; } // 补充内存释放逻辑,避免内存泄漏 cur = head; while (cur != NULL) { listw* temp = cur; cur = cur->next; free(temp); } return 0; }
额外注意点
- 动态申请的内存使用完成后必须释放,避免内存泄漏。
- 遍历链表优先使用临时指针,不要直接修改头指针,避免丢失链表入口。
内容的提问来源于stack exchange,提问作者iwannalearnforreal
相关产品推荐
相关产品推荐

