Python - 链表浅析
本篇用Python代码模拟链表
1. 链表介绍
概述
链表属于数据结构之 线性结构 的一种,每个节点都只能有 1个前驱 和 1个后继 节点。
作用
- 用于优化顺序表的弊端(如果没有足够的连续的内存空间,会导致扩容失败)。
- 链表扩容时,有地儿就行,连不连续无所谓。
组成
由 节点 组成,其中节点由以下两部分组成:
- 元素域 (数值域):存储数据。
- 链接域 (地址域):存储下一个节点的地址。
分类
根据节点类型不同,链表主要分为:
- 单向链表 :节点由1个数值域和1个地址域组成,前边节点的地址域存储的是后续节点的地址,最后1个节点的地址域为
None。 - 单向循环链表:尾节点的地址域指向头节点。
- 双向链表:节点包含前驱指针和后继指针。
- 双向循环链表 :双向链表的头尾相连。

2. 自定义代码模拟链表 - 思路分析
-
NodeObj类 (节点类)item: 数值域 (元素域)next: 地址域 (链接域)
-
LinkedList类 (链表类)- 属性 :
head: 表示头结点,指向第1个节点。
- 行为 (方法) :
is_empty(): 判断链表是否为空length(): 获取链表长度travel(): 遍历整个链表add(item): 链表头部添加元素append(item): 链表尾部添加元素insert(pos, item): 指定位置添加元素remove(item): 删除节点search(item): 查找节点是否存在
- 属性 :
-
测试 : 在
main模块中进行功能验证。
3. 代码实现
python
# 1. 自定义 NodeObj 类,表示节点类
class NodeObj:
# 初始化属性
def __init__(self, item):
self.item = item # 元素域 (数值域)
self.next = None # 链接域 (地址域)
# 2. 自定义 LinkedList 类,表示链表
class LinkedList:
# 1. 初始化属性
def __init__(self, node=None):
self.head = node # 链表的头结点,指向第1个节点
# 2. is_empty(self) 链表是否为空
def is_empty(self):
return self.head is None
# 3. length(self) 链表长度
def length(self):
count = 0
cur = self.head
while cur is not None:
count += 1
cur = cur.next
return count
# 4. travel(self) 遍历整个链表
def travel(self):
cur = self.head
items = []
while cur is not None:
items.append(str(cur.item))
cur = cur.next
print(" -> ".join(items))
# 5. add(self, item) 链表头部添加元素
def add(self, item):
"""头部插入,时间复杂度 O(1)"""
node = NodeObj(item)
node.next = self.head
self.head = node
# 6. append(self, item) 链表尾部添加元素
def append(self, item):
"""尾部追加,时间复杂度 O(n)"""
node = NodeObj(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = node
# 7. insert(self, pos, item) 指定位置添加元素
def insert(self, pos, item):
"""
:param pos: 从0开始索引
:param item: 插入的数据
"""
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
node = NodeObj(item)
count = 0
pre = self.head
# 移动到 pos 位置的前一个节点
while count < (pos - 1):
count += 1
pre = pre.next
# 执行插入
node.next = pre.next
pre.next = node
# 8. remove(self, item) 删除节点
def remove(self, item):
cur = self.head
pre = None
while cur is not None:
if cur.item == item:
# 判断是否是头结点
if pre is None:
self.head = cur.next
else:
pre.next = cur.next
return True # 删除成功
else:
pre = cur
cur = cur.next
return False # 未找到
# 9. search(self, item) 查找节点是否存在
def search(self, item):
cur = self.head
while cur is not None:
if cur.item == item:
return True
cur = cur.next
return False
# 3. 在 main 中测试
if __name__ == '__main__':
print("--- 测试节点类 ---")
# 3.1 测试节点类
node1 = NodeObj(10)
# 3.2 打印当前节点的 元素域 (数值域) 和 链接域 (地址域)
print(f'元素域 (数值域): {node1.item}') # 10
print(f'链接域 (地址域): {node1.next}') # None
print(f'node1 对象: {node1}') # 地址值
print(f'node1 的类型: {type(node1)}')
print('-' * 20)
print("\n--- 测试链表类 ---")
# 3.2 测试链表类
my_linkedlist = LinkedList(node1)
print(f'头结点为:{my_linkedlist.head}')
print(f'头结点的元素域:{my_linkedlist.head.item}') # 10
print(f'头结点的地址域:{my_linkedlist.head.next}') # None
print("\n--- 功能测试 ---")
# 测试是否为空
print(f"链表是否为空:{my_linkedlist.is_empty()}")
print(f"链表长度:{my_linkedlist.length()}")
# 遍历
print("当前链表内容:", end="")
my_linkedlist.travel()
# 头部添加
my_linkedlist.add(20)
print("头部添加 20 后:", end="")
my_linkedlist.travel()
# 尾部添加
my_linkedlist.append(30)
print("尾部添加 30 后:", end="")
my_linkedlist.travel()
# 指定位置插入
my_linkedlist.insert(1, 25)
print("位置 1 插入 25 后:", end="")
my_linkedlist.travel()
# 查找
print(f"查找 25 是否存在:{my_linkedlist.search(25)}")
print(f"查找 100 是否存在:{my_linkedlist.search(100)}")
# 删除
my_linkedlist.remove(25)
print("删除 25 后:", end="")
my_linkedlist.travel()
print(f"最终链表长度:{my_linkedlist.length()}")