优雅地移除节点

先来看一个不优雅的写法:

remove_list_entry(entry)
{
    prev = NULL;
    walk = head;

    while (walk != entry) {
        prev = walk;
        walk = walk->next;
    }

    if (!prev)
        head = entry->next;
    else
        prev->next = entry->next;
}

之所以说上面的代码不够优雅,相信大家肯定能感觉出来,主要就是需要对是否是头结点进行额外的判断,
因为使用了prev这个变量来辅助,那么怎么写才算是优雅呢?如下:

remove_list_entry(entry)
{
    indirect = &head;
    while ((*indirect) != entry)
        indirect = &((*indirect)->next);

    *indirect = entry->next;
}

这个代码是不是比上面的更简洁呢。不需要进行额外的处理,同样可以移除节点。

下面简单解释一下,

可以把indirect作为一个指向每个元素next成员的地址,注意不是下一个元素的地址!
(next成员也是元素的一部分,它也占有空间,也有地址)
下一个成员的地址是(*indirect)->next.

那么删除下一个元素节点,直接修改*indirect = new_elem就好了。(最后一行代码)
就是修改了当前节点next的指向。

当要移除head时,indirect为&head, *indirect = entry->next,就让head指向了下一个节点(移除了head).
不从进行额外的处理。

无论是在开始时,还是中间某个结点,indirect都是有意义的,不为NULL, 所以最后一行才可直接修改。

当然,indirect不论指向head还是next域,都是一个二级指针(类型一定)

如下图:

在这里插入图片描述

head是个指针,并非链表中的数据内容。

在这里插入图片描述


上面的两个代码片段是Linus大神在TED访谈时作的比较。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值