ku链接:非连续记忆体和linked list

由 ku链接 вт989点сс与酷游链接编译,2024/06/20。

从Linux 核心的艺术谈起

Linus Torvalds 在TED 访谈中提及自己的思维模式、性格与Linux 和Git 背后的心路历程。

于14:10时,他提到程式设计的"good taste" 为何。

对照CMU 教材Linked Lists


3 exceptional cases, we need to take care of:
list is empty
delete the head node
node is not in the list
以下的讨论不涵盖list is empty 和node is not in the list 的状况

原本的程式码(10 行)

void remove_list_node(List *list, Node *target)
{
    Node *prev = NULL;
    Node *current = list->head;
    // Walk the list
    while (current != target) {
        prev = current;
        current = current->next;
    }
    // Remove the target by updating the head or the previous node.
    if (!prev)
        list->head = target->next;
    else
        prev->next = target->next;
}

直观的写法会有特例,也就是第一笔资料与中间的资料的移去操作不同。

若要移去的是第一笔资料,那就需要把指标指向第一个节点;而若是要移除中间的资料,则须要把指标指向目标的前一个节点。

有「品味」的版本(4 行)

void remove_list_node(List *list, Node *target)
{
    // The "indirect" pointer points to the *address*
    // of the thing we'll update.
    Node **indirect = &list->head;
    // Walk the list, looking for the thing that 
    // points to the node we want to remove.
    while (*indirect != target)
        indirect = &(*indirect)->next;
    *indirect = target->next;
}

Linus Torvalds 换个角度来思考,通过指标的指标(或称「间接指标」,即indirect pointer) 来操作,如此一来,上面的特例就不存在。

Linus Torvalds 的解说:

People who understand pointers just use a "pointer to the entry pointer", and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing *pp = entry->next.

在15:25时,他说:

It does not have the if statement. And it doesn't really matter – I don't want you understand why it doesn't have the if statement, but I want you to understand that sometimes you can see a problem in a different way and rewrite it so that a special case goes away and becomes the normal case. And that's good code. But this is simple code. This is CS 101. This is not important – although, details are important.

重点是有时候我们可以从不同的角度来诠释问题,然后重写,那么例外就会消失,这样就是好的程式。

原本的方式是,有个指向前一元素的指标、另一个目前位置的指标,再利用while叙述逐一走访链结串列,找到target时停下来。这会有个分支判断prev是否为NULL,若为 就NULL代表target 是链结串列的head,因此需要把链结串列的head 指向下个元节点;若非NULL就把前个节点的next设为目前的下一个节点。

而Linus Torvalds 的想法则是拿一个指标指向「节点里头指向下个节点的指标」,以「要更新的位址」为思考点来操作。

有个指标的指标indirect,一开始指向head,之后一样走访list,解指标看是不是我们要的target,如果*indirect就是我们要移去的元素,代表indirect现在指向前一个节点里面的next指标,因此把*indirect设为target的下个节点,即可完成整个操作:

 

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值