ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

linus提到过的单链表删除节点算法

2021-09-13 01:02:28  阅读:224  来源: 互联网

标签:head 单链 next entry indirect prev linus 节点


linus 提到过的单链表删除节点算法

1 问题描述

在TED上做过一次访谈,linus提到了关于编程的品味,他举了一个例子:

linus在TED演讲_哔哩哔哩_bilibili

见原视频15'前后

image-20210912231607546

解法1

image-20210912231634945

解法2

这个例子要删掉一个链表的节点项

传入的参数是一个节点的引用

解法1,使用了prev

remove_list_entry(entry)
{
    prev = NULL;
    walk = head;
    while (walk && walk!=entry)
    {
        prev = walk;
        walk = walk->next;
    }
    
    // Remove the entry by
    // updating the head or previous entry
    if (!prev)
    {
        head = entry->next;
    }
    else
    {
        prev->next = entry->next;
    }
    
    // 释放节点空间
    free(entry);
}

解法2,使用了二重指针

remove_list_entry(entry)
{
    // The "inderect" pointer points to the
    // *address* of of the thing we will update
    indirect = &head;
    
    // Walk the list, looking for the thing that points to
    // entry we want to remove entry
    while ((*indirect)&&(*indirect)!=entry)
    {
        indirect = &(indirect->next);
    }
    
    // just remove the entry
    *indirect = entry->next;
    free(entry);
}

2 思路

解法1,是常用的解法

一般情况

用一个前驱节点 prev 来寄存待删除节点之前的节点

用图形表示就是

image-20210912234134071

这样,就能实现将prev指向entry的后继节点

特殊情况

为了保证可靠性,也需要考虑到

  • 整个链表只有2个节点的情况

image-20210912234642850

此时需要我们判断 prev=NULL

并让head->next直接指向entry->next

  • 整个链表只有1个节点的情况

image-20210912234842119

此时可能需要直接释放 head 所指向的节点空间

并让head指向NULL

解法2

二重指针

指针是一次寻址

二重指针是二重寻址

indirect=&head

head本身是指向一个节点的指针,而indirect存储了head的地址,所以是存储指针的容器

这里不得不提到节点的定义

typedef struct ListNode
{
    ListNode* next;
    int data;
} ListNode;

每个节点其实都存储了

  1. 下一个节点的地址
  2. 本身数据

大概类似这样

image-20210912235331628

注意我在上面加了一个地址0x0000000

其实next的内容,就是地址,指针就是保存了地址的变量。

那么把整个链表放在一起看,是这样的:

image-20210912235953020

每个节点的next字段,都保存了它下一个节点的地址

那么,我们可以认为,每个节点的next字段就是一个指针变量

而 indirect = &head

就是一个二重指针

indirect存放了head的地址

可以通过解引用运算获取head里面的值

具体操作

那么,究竟如何完成删除一个节点的功能?

image-20210913000939965

为了方便叙述,给每个next字段都加上一个地址 ,分别记作ABCD

假设我们要删掉0x00000008这个节点

此时indirect已经指向head了

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

这段循环,让indirect指向了 存放entry地址 的next字段

即此时 indirect = B

此时,如果让B里面的内容,从0x00000008变为0x00000010

就能完成删除节点,维护链表的操作

代码如下

    // just remove the entry
    *indirect = entry->next;
    free(entry);

示意图

image-20210913001200419

特殊情况处理

像其他的情况,如

  • 只有2个节点,head节点和entry节点
  • 只有entry节点(即entry节点就是head节点)

也可以很好的解决,如有兴趣可以自己实现一下。

对编程的爱好,让我充满力量,加油!

标签:head,单链,next,entry,indirect,prev,linus,节点
来源: https://www.cnblogs.com/studentWangqy/p/15260743.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有