- 我的第一本算法书
- (日)宫崎修一 石田保辉
- 959字
- 2020-08-29 01:37:54
1-2 链表
链表是数据结构之一,其中的数据呈线性排列。在链表中,数据的添加和删除都较为方便,就是访问比较耗费时间。
01
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0026_0001.jpg?sign=1738973917-Fod3PwKRmhdzKnr17kdKF1MLvI1rcUMV-0-81624118112c49238ee3f45829044d3f)
这就是链表的概念图。Blue、Yellow、Red这3个字符串作为数据被存储于链表中。每个数据都有1个“指针”,它指向下一个数据的内存地址。
02
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0026_0002.jpg?sign=1738973917-fsYx1A9hHxNBoVj0woqGm7hCC7DOLXBc-0-4af5159f9c00818a7f0a8489d9b88381)
在链表中,数据一般都是分散存储于内存中的,无须存储在连续空间内。
03
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0026_0003.jpg?sign=1738973917-JYWBMi2rjv2cYBgZouUTqKge7rnrRZYA-0-1f6ce3b498889a6208cf6809d730b5e9)
因为数据都是分散存储的,所以如果想要访问数据,只能从第1个数据开始,顺着指针的指向一一往下访问(这便是顺序访问)。比如,想要找到Red这一数据,就得从Blue开始访问。
04
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0027_0001.jpg?sign=1738973917-Sk3H0rSOAckBBI3xqdine93YGFS9Bzbd-0-626768f50b24c006911fcd756036ff8e)
这之后,还要经过Yellow,我们才能找到Red。
05
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0027_0002.jpg?sign=1738973917-32yJcvFbLRsVgOlKaLvym1y5kQ0XofHU-0-dabbc77743b93ecc37cb12292ebdc23e)
如果想要添加数据,只需要改变添加位置前后的指针指向就可以,非常简单。比如,在Blue和Yellow之间添加Green。
06
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0027_0003.jpg?sign=1738973917-77ppwDAGXnt2VH5EXNwFEtL9UxNykYqm-0-a60b8306c64b27c7bfe28f526f02ec37)
将Blue的指针指向的位置变成Green,然后再把Green的指针指向Yellow,数据的添加就大功告成了。
07
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0027_0004.jpg?sign=1738973917-RFeW4jtJFkTrBbxIF724VyqpFTNN6yko-0-c06807614767393bf52e076474ab5fe4)
数据的删除也一样,只要改变指针的指向就可以,比如删除Yellow。
08
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0027_0005.jpg?sign=1738973917-u5Fee0zu7uDMvVPOCxHqjv5jbCw3FL1Y-0-ecb5fe938b517f9c7ef6c77d8623dc8c)
这时,只需要把Green指针指向的位置从Yellow变成Red,删除就完成了。虽然Yellow本身还存储在内存中,但是不管从哪里都无法访问这个数据,所以也就没有特意去删除它的必要了。今后需要用到Yellow所在的存储空间时,只要用新数据覆盖掉就可以了。
解说
对链表的操作所需的运行时间到底是多少呢?在这里,我们把链表中的数据量记成n。访问数据时,我们需要从链表头部开始查找(线性查找),如果目标数据在链表最后的话,需要的时间就是O(n)。
另外,添加数据只需要更改两个指针的指向,所以耗费的时间与n无关。如果已经到达了添加数据的位置,那么添加操作只需花费O(1)的时间。删除数据同样也只需O(1)的时间。
参考:3-1线性查找
补充说明
上文中讲述的链表是最基本的一种链表。除此之外,还存在几种扩展方便的链表。
虽然上文中提到的链表在尾部没有指针,但我们也可以在链表尾部使用指针,并且让它指向链表头部的数据,将链表变成环形。这便是“循环链表”,也叫“环形链表”。循环链表没有头和尾的概念。想要保存数量固定的最新数据时通常会使用这种链表。
循环链表
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0028_0003.jpg?sign=1738973917-cHljCy1I0GdRLQkiweTHCwB0pNgwacnD-0-eaa92feccc04ab4978e604405195fa6d)
另外,上文链表里的每个数据都只有一个指针,但我们可以把指针设定为两个,并且让它们分别指向前后数据,这就是“双向链表”。使用这种链表,不仅可以从前往后,还可以从后往前遍历数据,十分方便。
但是,双向链表存在两个缺点:一是指针数的增加会导致存储空间需求增加;二是添加和删除数据时需要改变更多指针的指向。
双向链表
![](https://epubservercos.yuewen.com/0B1C2F/13354221605522106/epubprivate/OEBPS/Images/figure_0028_0004.jpg?sign=1738973917-9ByiXVvQ65ABZLSb3CT6DfiSYIyIYobN-0-5dba72ed6d8c7cd2bb12160cb35d13a9)