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

双向链表head持续被设为NULL问题求助

问题分析与解决方案

核心错误:全局head未被正确更新

你的代码中,AddNode和AddNodeAt函数返回了新的链表头,但main函数里没有将返回值赋值给全局的head变量。因为函数参数是传值传递,函数内部修改的head只是局部变量,全局head始终保持初始的NULL,这是所有功能失效的根本原因。

比如main里的调用应该改成:

head = AddNode(head, value);

和

head = AddNodeAt(head, position, value);

其他关键错误

1. 结构体定义错误

结构体内部不能直接使用node别名,因为typedef struct node node;是在结构体定义之后,所以结构体中的指针必须写成struct node*:

struct node {
    struct node *prev;  // 修正前是node *prev;
    int val;
    struct node *next;  // 修正前是node *next;
};
typedef struct node node;

2. AddNodeAt函数的逻辑漏洞

  • 未处理malloc失败的情况:如果malloc返回NULL,后续操作会导致崩溃,需要添加判断。
  • 未处理头部插入(position=1)的场景:当插入到链表头部时,需要直接更新head,并处理新节点的prev和next。
  • 位置遍历逻辑错误:要插入到第position个位置(从1开始计数),需要找到第position-1个节点作为前驱,原代码的循环会跳过目标前驱节点。
  • 重复调用ListLength导致冗余输出:多次调用ListLength会重复打印链表长度,应该先获取一次长度存到变量中复用。
  • 空链表插入position=1时的崩溃问题:原代码中当链表为空且position=1时,会进入末尾插入分支,此时temp是NULL,访问temp->next会触发崩溃。

修正后的完整代码

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

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

node *head;

node *AddNode(node *head, int value)
{
    node *ptr = (node *)malloc(sizeof(node));

    if (!ptr) {
        printf("No Memory Available");
        return head;
    }
    ptr->val = value;
    ptr->next = NULL;
    ptr->prev = NULL;

    if (!head) {
        head = ptr;
    } else {
        node *temp = head;
        while (temp->next) {
            temp = temp->next;
        }
        temp->next = ptr;
        ptr->prev = temp;
    }
    return head;
}

int ListLength(node *head)
{
    int count = 0;

    if (head == NULL) {
        return 0;
    } else {
        node *temp = head;
        count = 1;
        while (temp->next != NULL) {
            temp = temp->next;
            count++;
        }
        return count;
    }
}

node *AddNodeAt(node *head, int position, int value)
{
    node *ptr = (node *)malloc(sizeof(node));
    if (!ptr) {
        printf("No Memory Available");
        return head;
    }
    ptr->val = value;
    ptr->next = NULL;
    ptr->prev = NULL;

    int len = ListLength(head);
    // 边界判断
    if (position < 1 || position > len + 1) {
        printf("Invalid position");
        free(ptr); // 避免内存泄漏
        return head;
    }

    // 插入到头部
    if (position == 1) {
        ptr->next = head;
        if (head != NULL) {
            head->prev = ptr;
        }
        head = ptr;
    }
    // 插入到尾部
    else if (position == len + 1) {
        node *temp = head;
        while (temp->next) {
            temp = temp->next;
        }
        temp->next = ptr;
        ptr->prev = temp;
    }
    // 插入到中间
    else {
        node *temp = head;
        // 找到第position-1个节点
        for (int i = 1; i < position - 1; i++) {
            temp = temp->next;
        }
        ptr->next = temp->next;
        ptr->prev = temp;
        if (temp->next != NULL) {
            temp->next->prev = ptr;
        }
        temp->next = ptr;
    }
    return head;
}

void PrintList(node *head)
{
    node *temp = head;
    if (!head) {
        printf("list empty");
    } else {
        while (temp != NULL) {
            printf("%d", temp->val);
            if (temp->next != NULL) {
                printf("->");
            }
            temp = temp->next;
        }
    }
}

void PrintLength(node *head)
{
    int len = ListLength(head);
    if (len == 0) {
        printf("\nEmpty List\n");
    } else {
        printf("\n%d nodes\n", len);
    }
}

int main() {
    int value = 0;
    int num = 0;
    int position = 0;
    printf("Number of nodes to be made: ");
    scanf("%d", &num);
    for (int i = 1; i <= num; i++) {
        printf("value in node number %d: ", i);
        scanf("%d", &value);
        head = AddNode(head, value);
    }
    PrintList(head);
    PrintLength(head);

    printf("\nPosition of new node: ");
    scanf("%d", &position);
    printf("\nValue of new node:");
    scanf("%d", &value);
    head = AddNodeAt(head, position, value);

    PrintList(head);
    PrintLength(head);

    return 0;
}

额外优化说明

  • 将ListLength改为只返回长度,单独写PrintLength函数负责打印,避免不必要的输出。
  • 修正PrintList的循环逻辑,确保最后一个节点后不会多打印箭头。
  • 在AddNodeAt中,当位置无效时释放已分配的内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:35:06