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

C语言双向链表删除首尾节点为何需返回指针?指针传值疑惑

双向链表删除节点的指针传递问题

先看这段删除双向链表节点的C语言函数:

#include <stdlib.h>

typedef struct node {
    struct node *before;
    struct node *next;
    // 可按需添加数据域
} node;

node *delete(int x, node *new)
{
    node *del = new;
    for (int i = 0; i < x; i++)
    {
        del = del->next;
    }

    // 删除首节点
    if (del->before == NULL)
    {
        del = del->next;
        node *rem = del->before;
        del->before = NULL;
        new = del;
        free(rem);
        return new;
    } 

    // 删除尾节点
    else if (del->next == NULL)
    {
        del = del->before;
        node *rem = del->next;
        del->next = NULL;
        free(rem);
        return new;
    }

    // 删除中间节点
    else
    {
        del->before->next = del->before->next->next;
        del->next->before = del->next->before->before;
        free(del);
        return new;
    }
}

核心原因:C语言的指针是按值传递

C语言中所有参数都是按值传递,指针也不例外。函数里的new是你传入的链表头指针的副本——它和主函数里的原指针指向同一块内存,但本身是两个独立的变量。

1. 删除中间节点无需返回的原因

删除中间节点时,我们修改的是链表节点内部的指针成员:把被删节点的前一个节点的next指向后一个节点,后一个节点的before指向前一个节点。这些操作直接修改了堆内存中节点结构体的内容,主函数里的头指针本身没有变化(依然指向原来的头节点),所以外部能直接看到链表结构的更新,不需要修改头指针的值。

2. 删除首/尾节点的区别

  • 删除首节点:原来的头节点被释放,必须让主函数里的链表头指针指向新的头节点(原第二个节点)。但函数里的new是原指针的副本,修改new = del只是改变了副本的值,主函数里的原指针完全不受影响。因此必须把新的头指针返回,让主函数重新赋值(比如head = delete(0, head);),才能更新外部的链表指针。
  • 删除尾节点:这里返回new其实是多余的——头指针本身没有变化,我们只是修改了倒数第二个节点的next为NULL,主函数里的头指针依然指向原头节点,链表尾端已经被正确截断。你测试时觉得需要返回,只是因为代码里统一写了return,实际不返回也不影响结果。

补充优化建议

如果不想通过返回值更新头指针,可以改用指向指针的指针作为参数,直接修改主函数里的指针变量。比如把函数签名改成void delete(int x, node **new),删除首节点时直接修改*new = del,就能同步更新外部的头指针,无需返回值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:25:33