如何初始化双向链表尾指针以避免段错误?
双向链表段错误修复及插入功能实现
问题根源
你的代码中tail指针始终未被正确赋值,一直保持初始的NULL状态:
show_last函数直接访问tail->value,对空指针解引用触发段错误;- 所有节点的
prev_link被错误赋值为NULL,双向链表的反向关联完全失效; - 内存释放逻辑错误,仅释放了个别节点,存在严重内存泄漏。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> typedef struct Node { int value; struct Node *next_link; struct Node *prev_link; } Node; Node *create_node(int value) { Node *new_node = malloc(sizeof(Node)); new_node->value = value; new_node->next_link = NULL; new_node->prev_link = NULL; return new_node; } void forward_traversing(Node *head) { Node *temp = head; while (temp != NULL) { printf("%d ", temp->value); temp = temp->next_link; } printf("\n"); } void backward_traversing(Node *tail) { Node *temp = tail; while (temp != NULL) { printf("%d ", temp->value); temp = temp->prev_link; } printf("\n"); } void show_first(Node *head) { if (head == NULL) { printf("List is empty\n"); return; } printf("%d is the first value\n", head->value); } void show_last(Node *tail) { if (tail == NULL) { printf("List is empty\n"); return; } printf("%d is the last value\n", tail->value); } // 头部插入函数 void insert_at_head(Node **head, Node **tail, int value) { Node *new_node = create_node(value); if (*head == NULL) { *head = new_node; *tail = new_node; } else { new_node->next_link = *head; (*head)->prev_link = new_node; *head = new_node; } } // 尾部插入函数 void insert_at_tail(Node **head, Node **tail, int value) { Node *new_node = create_node(value); if (*tail == NULL) { *head = new_node; *tail = new_node; } else { new_node->prev_link = *tail; (*tail)->next_link = new_node; *tail = new_node; } } // 在指定节点后插入 void insert_after_node(Node **tail, Node *prev_node, int value) { if (prev_node == NULL) { printf("Previous node cannot be NULL\n"); return; } Node *new_node = create_node(value); new_node->next_link = prev_node->next_link; prev_node->next_link = new_node; new_node->prev_link = prev_node; // 如果原节点是尾节点,更新tail指针 if (new_node->next_link == NULL) { *tail = new_node; } else { new_node->next_link->prev_link = new_node; } } int main() { Node *head = NULL , *temp = NULL , *tail = NULL; // 修复链表创建逻辑 for (int i = 25; i >= 0; i--){ temp = create_node(i); if (head == NULL) { // 第一个节点,同时作为头和尾 head = temp; tail = temp; } else { // 新节点的next指向当前头 temp->next_link = head; // 当前头的prev指向新节点 head->prev_link = temp; // 更新头指针 head = temp; } } printf("Forward traversal: "); forward_traversing(head); printf("Backward traversal: "); backward_traversing(tail); show_first(head); show_last(tail); // 测试头部插入 insert_at_head(&head, &tail, -1); printf("\nAfter inserting -1 at head:\n"); forward_traversing(head); show_first(head); // 测试尾部插入 insert_at_tail(&head, &tail, 26); printf("\nAfter inserting 26 at tail:\n"); forward_traversing(head); show_last(tail); // 测试指定节点后插入(找value为10的节点) Node *target = head; while (target != NULL && target->value != 10) { target = target->next_link; } if (target != NULL) { insert_after_node(&tail, target, 100); printf("\nAfter inserting 100 after node 10:\n"); forward_traversing(head); } // 正确释放所有节点 Node *current = head; while (current != NULL) { Node *next = current->next_link; free(current); current = next; } return 0; }
关键修改说明
- 链表创建逻辑:
- 首次创建节点时,同时初始化
head和tail,确保尾部指针有效; - 每次插入头部时,同步维护原头节点的
prev_link,保证双向关联正确。
- 首次创建节点时,同时初始化
- 空指针防护:
- 在
show_first和show_last中增加空指针判断,避免链表为空时触发错误。
- 在
- 内存释放:
- 遍历整个链表逐个释放节点,彻底避免内存泄漏和重复释放问题。
插入功能说明
- 头部插入:传入
head和tail的指针(因为需要修改指针本身),处理空链表和非空链表两种情况; - 尾部插入:同理,维护尾节点的
next_link和新节点的prev_link,并更新tail; - 指定节点插入:找到目标节点后,插入新节点并维护前后关联,若插入位置在尾部则同步更新
tail。
内容的提问来源于stack exchange,提问作者Moonwalker
相关产品推荐
相关产品推荐

