这两种“移除单向链表中指定元素”的代码,你觉得那个更好?

2018-08-13 17:32:14 +08:00
 lxy42

这两段代码我是在Linus Torvalds 在 TED 上的一个演讲看到的。

代码如下:

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

    // Walk the list

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

    // Remove the entry by updating the
    // head or the previous entry

    if(!prev)
        head = entry->next;
    else
        prev->next = entry->next;
}
remove_list_entry(entry){
    // The "indirect" pointer points to the
    // *address* of the thing we'll update

    indirect = &head;

    // walk the list, looking for the thing that 
    // points to the entry we want to remove

    while((*indirect) != entry)
        indirect = &(*indirect)->next;
    
    // .. and just remove it
    *indirect = entry->next;
}

第一个函数的实现方式符合大多数人的直觉,说实话,第二个函数我之前从未看到过,它的实现方式确实更优雅和巧妙,消除了多余的 if。

2358 次点击
所在节点    编程
7 条回复
thinkmore
2018-08-15 09:49:38 +08:00
第二个做法我也没看懂,但我知道另外一个解法

将需要移除的元素赋值给 before.
比如 a-->b-->c--->d 现在需要移除 c 编程 a--->b--->d
c.value = d.value;
c.next = null;
lxy42
2018-08-15 09:58:28 +08:00
@thinkmore #1 你可以看一下原视频,或许对理解第二种方法有点帮助。
这里的第二种方法使用的 indirect 变量是一个指向节点( Node )中 next 的指针,所以实际上 indirect 的类型是 Node**。所以当找到需要移除的节点时,直接更新 indirect 的值就可以了。
lxy42
2018-08-15 10:07:14 +08:00
@thinkmore #1 我不太理解你的解法,假如要移除 b 呢,应该怎么做?
thinkmore
2018-08-15 10:15:57 +08:00
忘记 c 语言了。。里面还夹杂这&运算,就更无力了。

这样也可以完成移除 b,只是一种比较取巧的方式
b.value = b.next.value // b,c 数据一致,可以认为 b 就是 c
b.next = c.next;//b 指向 d 了

就变成了 a-->c--->d
lxy42
2018-08-15 10:27:59 +08:00
@thinkmore #4
下面是我对你的算法写的伪代码:

```
remove_list_entry(entry){
walk = head;

while(walk != entry)
walk = walk->next;

if(walk->next != NULL){
walk->val = walk->next->val;
walk->next = walk->next->next;
}else{
// 移除末尾元素
// 为了移除末尾元素,似乎还是需要用一个变量保存前一个节点
// prev->next = NULL
}
}
```
xuanbg
2018-08-24 08:06:35 +08:00
只要把要移除的节点的上一个节点的 next 指向下一个节点的地址就好了呀。

例如:A->B->C->D->E,要移除 C 的话,只需要把 B 的下一个节点的地址从 C 改成 D 就变成了:A->B->D->E
lxy42
2018-08-24 17:24:58 +08:00
@xuanbg #6 算法是这样没错,我的重点是讨论这两种具体的实现方式。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/479421

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX