Python 链表


在本文中我们来简单聊一聊Python的链表。
首先我们要先了解一下什么是链表,它于数组(列表)有什么区别。链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
首先说一说单链表:
****
上图是一个单链表,那么在Python中我们应该如何实现这个单链表呢?在数据的插入过程中,我们有两种插入方式,头插法和尾插法,顾名思义,就是在头部插入元素和尾部插入元素。
头插法的特点就是,把新元素的next指向头节点,再把头节点赋值为新元素:

class Node:  
    def __init__(self, item):  
        self.item = item  
        self.next = None  
def creat_linklist_head(li):  # 头插法  
    head = Node(li[0])  
    for element in li[1:]:  
        node = Node(element)  
        node.next = head  
        head = node  
    return head

尾插法则不同,当只有一个元素时,head指针和tail指针同时指第一个元素。当新元素插入时,将尾指针指向该元素,再将尾指针赋值为新元素值。

def creat_linklist_tail(li):  # 尾插法  
    head = Node(li[0])  
    tail = head  
    for element in li[1:]:  
        node = Node(element)  
        tail.next = node  
        tail = node  
    return head

来看一看单链表的插入和删除。
****
我们假设p是待办元素,它的上一个元素是curnode。在插入时我们要注意,先执行 p.next = curnode.next,以图为例,有的看官回想,为什么不先把p和a连上,因为我们会发现,在连接p和a的时候,a于c断开,没有人和c相连,那么c就会无法被寻找,换句话说,这个元素就游荡在茫茫数据之中。因此,再已知只有curnode和p的前提下,要先连接x和后面的元素,然后再执行 curnode.next = p。
****
那么在删除时呢,我们可以仿照插入时,将p后的元素连接到curnode后面,然后删除p即可。那么我们总结一下单链表插入删除方式如下:

 # 插入元素
 p.next = curnode.next
 curnode.next = p
 # 删除元素
 curnode.next = p.next
 del p

再来看一看双链表,从单链表我们可以看到一个弊端,那就是我们无法向前寻找元素,那么双链表就很好的解决了这一问题。
****
如上图所示,双链表还有个头指针指向上一元素,那么双链表的插入和删除又该如何实现呢?
首先是插入元素:
****
由上图,当一个新元素p到来时,我们需要执行这四个操作

p.next = curnode.next
curnode.next.prev = p
p.prev = curnode
curnode.next = p

然后是删除元素:
****
由上图,当我们想删除元素p时,我们需执行如下操作:

curnode.next = p.next
p.next.prev = curnode
del p

这就是数据结构—-链表的大致原理,各位看官有什么不懂的欢迎在评论区留言。


文章作者: Runze_Li
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Runze_Li !