链表的意义
链表(link) 是一种长度几乎不受限制的数据结构。不同于列表,链表各个节点的内存位置不是连续的。
比如:
你的电脑内存被病毒占满了(真是一种神奇的病毒),只有3号内存、5号内存、6号内存、21号内存、92号内存为空。而你制作的杀毒软件必须占用4个内存空间(也是一种神奇的杀毒软件),如果你不知道链表,而把所有程序装在一个列表中,那么因为列表两个值的内存是连续的,所以,杀毒软件的安装无法成功(列表最长只能占2个内存,安装在5号内存和6号内存中)。这时,链表来了:
链表: 我可以成功安装杀毒软件。
你:怎么办?
链表:在我这里,各个节点的内存位置不是连续的。
你:你是怎么做到的?
链表:首先,我每一个节点都由两部分构成:数据域和指针域。前一个指针域指向下一个值。
你:哦,让我思考思考。
终于, 在链表的帮助下,你的电脑恢复了正常。
基本操作
我相信,你一定很想知道你是怎么实现的链表,修复你的电脑——你对刚才发生的事情一无所知(画外音:那当然,刚才的事是你编的。)。因为,在python中,并不存在指针类型。
初始化
我们知道,链表的各个节点的内存位置不是连续的,每个节点由数据域和指针域构成,所以,在__init__
函数中,我们定义两部分
class Link: # 创建一个link类
def __init__(self, data=None, p=None):
self.data = data # 添加数据域
self.p = p # 添加指针域
str函数打印链表
你说:那我依然不认为这个链表各个节点的内存位置不是连续的。别急,慢慢来。
在这之后,我需要用__str__
函数打印出整个链表,那么,我直接让一个节点的指针域等于下一个节点,再通过一点点递归算法,打印出链表。
def __str__(self): # 返回整个链表
return '{} -> {}'.format(self.data, self.p)
在链表尾部添加一个值(尾插法)
重头戏来了,许多人问:“作者,什么叫:‘我直接让一个节点的指针域等于下一个节点’啊?我觉得指针域就是None呀。”
作者:格局小了。
我们先来看,如何在链表尾部添加一个值。按照我“直接让一个节点的指针域等于下一个节点”的思路,添加值时,我们只要把最尾部的节点的指针域改为需要连接的链表。
至于如何找到最尾部的节点,我们用一个小小的递归……
def __add__(self, other):
tail = self.p
if not tail: # 链表节点的指针域为空
self.p