You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除循环双向链表尾节点时出现无限内存地址输出问题求助

问题分析与修复

你的程序进入无限循环的根源不在deleteFromEnd函数,而是insertAtBeg函数漏掉了关键的指针更新步骤,导致双向循环链表的prev链接不完整,最终引发遍历(printList)时的无限循环。

具体问题点

在insertAtBeg函数中,当链表已有节点时,你只更新了尾部节点的next、新节点的prev和next,但没有将原头部节点的prev指向新节点。这会导致链表的双向链接断裂,printList遍历到原头部节点时,它的prev指针仍然指向旧的尾部节点,无法形成正确的循环,最终触发无限循环。

修复后的代码

首先修正insertAtBeg函数,补充缺失的指针更新:

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int data;
    struct node* next;
    struct node* prev;
} node;

void printList(node* head_ref) { // 打印所有节点
    if(head_ref == NULL) { // 如果链表中没有节点
        printf("没有节点可打印,请先添加节点!\n");
        return ;
    }
    node* tail = head_ref;
    do {
        printf("%d ", tail->data);
        tail = tail->next;
    } while(tail != head_ref);
    
    printf("\n");
}
void insertAtBeg(node** head_ref, int data) { // 在头部插入节点
    node* newNode = (node*)malloc(sizeof(node));
    newNode->data = data;
    
    if(*head_ref == NULL) { // 如果链表中没有节点,将自身链接
        newNode->next = newNode;
        newNode->prev = newNode;
        *head_ref = newNode;
        return ;
    }
    node* tail = (*head_ref)->prev;
    
    tail->next = newNode;
    newNode->prev = tail;
    newNode->next = *head_ref;
    // 补充这一步:将原头部节点的prev指向新节点
    (*head_ref)->prev = newNode;
    *head_ref = newNode;
}

void deleteFromEnd(node** head_ref) { // 从尾部删除节点
    if(*head_ref == NULL) { // 如果链表中没有节点
        printf("没有节点可打印,请先添加节点!\n");
        return ;
    }

    node* tail = (*head_ref)->prev; // 链表的最后一个节点
    node* temp = tail; // 要删除的节点,直接复用tail即可,不用重复赋值
    
    if (*head_ref == tail) { // 如果链表中只有一个节点
        *head_ref = NULL;
    }
    else {
        tail->prev->next = *head_ref;
        (*head_ref)->prev = tail->prev;
    }
    free(temp);
}
int main() {
    node* head = NULL;
    
    // 在头部插入节点
    insertAtBeg(&head, 1);
    insertAtBeg(&head, 2);
    insertAtBeg(&head, 3);
    insertAtBeg(&head, 4);
    insertAtBeg(&head, 5);
    printList(head); // 打印所有节点
    
    // 从尾部删除节点
    
    deleteFromEnd(&head);
    printList(head);
    deleteFromEnd(&head);
    printList(head);
    deleteFromEnd(&head);
    printList(head); // 打印所有节点
    
    return 0;
}

额外优化说明

  • deleteFromEnd函数中,node* temp = (*head_ref)->prev;可以直接写成node* temp = tail;,避免重复计算,代码更简洁。
  • 当链表只剩一个节点时,tail = NULL;是多余的,因为tail是局部变量,不会影响外部状态,直接设置*head_ref = NULL即可。

运行结果

修复后程序输出如下:

5 4 3 2 1 
5 4 3 2 
5 4 3 
5 4 

内容的提问来源于stack exchange,提问作者Tolga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:00:39