本文章是通过Python实现链表的一系列操作,具体的关于链表的一些基础知识点
详见:数据结构3线性表------单链表(C)-CSDN博客
其他数据结构内容可见:数据结构_Gu_shiwww的博客-CSDN博客
1 链表前言
1.1 节点的构建

Python中链表以及链表节点的构建均是通过class类来进行构建:
python
# 定义一个类
class Node:
"""创建单链表节点"""
def __init__(self, data=None):
self.data = data # 数据域
self.next = None # 引用域 ,引用指向自身结构体的类型(存放的下一个节点的地址)
定义一个Node类,通过构造函数__init__()来初始化两个类中的变量,一个是数据域data,一个是指针域next
1.2 遍历单向链表
1.2.1 遍历无头的单向链表
无头单向链表,即链表内的每一个节点的数据域的引用都是有效的
python
current = self.head
while current:
print(current.data)
current = current.next
定义current指向链表中的头节点,while循环的条件就是判断current是否为空,若current有指向节点,则进入while循环进行current的移动
1.2.2 遍历带头的单向链表
带头的单向链表,头节点的数据域是无效的,但是指针域有效
python
current = self.head
while current.next:
current = current.next
print(current.data)
因为头指针下一定有一个头节点,但此节点数据无效,故while的循环执行条件是查看current的next域是否有内容。若while循环条件成立,需要先将current的指针进行后移,之后再打印内部的数据。
【练习】构建几个节点,之间用next指针连接在一起,按照next指针域进行逐个打印(用不带头节点的方式)
python
class Node:
def __init__(self, data):
self.data = data
self.next = None
a, b, c, d = Node('A'), Node('B'), Node('C'), Node('D')
a.next = b
b.next = c
c.next = d
current = a
while current:
print(current.data)
current = current.next
2 有头单向链表的操作函数
P.1 给出链表操作的各个函数接口
python
class Node:
"""创建单链表节点"""
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self):
# 初始化一个头节点,它不包含实际数据,仅作为链表的起始标志
self.head = Node()
# 1.判断单向链表是否为空 1代表空 0代表非空
def is_empty(self):
pass
# 2.求单向链表长度的函数
def length(self):
pass
# 3.向单向链表的指定位置插入数据
# post 插入的位置 data插入的数据
def insert(self, position, data):
pass
# 4.遍历单向链表
def show(self):
pass
# 5.删除单向链表中指定位置的数据 post 代表的是删除的位置
def delete_position(self, position):
pass
# 6.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
def delete_data(self, data):
pass
# 7.查找指定数据出现的位置 data被查找的数据 //search 查找
def search_data(self, data):
pass
# 8.转置链表
def reverse(self):
pass
# 9.清空单向链表
def clear(self):
pass
# 10.修改指定位置的数据 post 被修改的位置 data修改成的数据
def change_data(self, position, data):
pass
P.2 判断单向链表是否为空
python
# 1.判断单向链表是否为空 1代表空 0代表非空
def is_empty(self):
return self.head.next is None
带头节点的单链表,判断链表是否为空,可以查看头节点后面是否还连有节点。self.head指向链表的头节点,通过next域访问到头节点的下一个节点,若next为空则链表为空。函数可以返回self.head.next is None的判断结果。注意因为是链表,可以无限增加长度,不需要判断链表是否为满。
P.3 求单向链表的长度
python
# 2.求单向链表长度的函数
def length(self):
current = self.head
length = 0
while current.next:
current = current.next
length += 1
return length
在求链表长度的函数中,不能直接对self.head,即头指针进行挪用,因为头节点被挪用之后,链表前面的元素不能再通过遍历head指针得到,只能再定义一个变量current,通过移动current来遍历整个链表,后续的函数中会经常出现定义一个current变量指向头指针,
P.4 向指定位置插入数据
python
# 2.向单向链表的指定位置插入数据
# post 插入的位置 data插入的数据
def insert(self, position, data):
# 容错判断
if position < 0 or position > self.length():
print("insert error")
return
# node新节点
new_node = Node(data)
# 移动伪指针到插入位置的前一个位置
current = self.head
for _ in range(position):
current = current.next
# 插入动作(先连后面,再连前面)
new_node.next = current.next
current.next = new_node
首先进行容错判断,插入的位置,即下标要大于0并且小于链表的长度,判断完之后创建一个新的节点new_node,定义current指向头指针,通过for循环遍历到要插入元素的前面一个位置,然后通过next指针将元素插入
P.5 单链表的遍历
python
# 3.遍历单向链表
def show(self):
current = self.head
while current.next:
current = current.next
print(current.data, end=' ')
print()
遍历比较简单,因为是带头结点的单链表,注意while的判断条件是current.next,然后通过遍历逐个打印节点的data域
P.6 删除指定位置的数据

python
# 5.删除单向链表中指定位置的数据 post 代表的是删除的位置
def delete_position(self, position):
# 容错判断
if self.is_empty() or position < 0 or position >= self.length():
print("delete_position error")
return
current = self.head
# current走到删除位置的前一个位置
for _ in range(position):
current = current.next
# 删除动作
current.next = current.next.next
首先容错判断,判断position是否合法,并且判断链表是否为空,若为空则无节点可删,用current指向头元素,for循环遍历current到被删除节点的前一个位置,删除该数据(在Python中无需手动free被断开的节点,是因为Python中有垃圾回收机制,若该节点无任何引用指向它,解释器会自动回收该处空间)
P.7 删除所有出现的指定数据

python
# 6.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
def delete_data(self, data):
if self.is_empty():
print("delete_data error")
return
current = self.head
while current.next:
if current.next.data == data:
current.next = current.next.next
else:
current = current.next
首先容错判断,只需要判断是否为空链表,其次遍历整个链表(因为要删除所有对应的元素)用一个分支语句去执行操作,如果节点的data域等于传递的参数data,则执行删除操作,否则链表自动继续遍历
P.8 查找指定元素的下标
python
# 9.查找指定数据出现的位置 data被查找的数据 //search 查找
def search_data(self, data):
if self.is_empty():
print("search_data error")
return
current = self.head
position = 0
while current.next:
current = current.next
if current.data == data:
return position
position += 1
return -1
首先容错判断,空链表不可能存在指定元素,其次遍历整个链表,用一个变量position来记录当前遍历到的节点的下标,若某个节点的data域与传递的参数data相同,则返回下标position,否则整个链表遍历结束,返回-1
P.9 链表的转置

python
# 10.转置链表
def reverse(self):
# 断开前,保存头节点的下一个节点的地址
current = self.head.next
# 断开链表
self.head.next = None
# 遍历无头单向链表,把无头单向链表的节点头插到有头空链表中
while current:
# 提前将current的下一个节点保存起来
next_node = current.next
# 先连后面,再连前面, 将无头表的节点插入头结点的下一个位置
current.next = self.head.next
self.head.next = current
# 将current移动,指向下一个节点
current = next_node
P.10 清空单向链表
python
# 11.清空单向链表
def clear(self):
self.head.next = None
只要断开头节点后面的节点,Python会自动执行垃圾回收机制,回收后面的节点
P.11 修改指定位置的数据
python
# 8.修改指定位置的数据 post 被修改的位置 data修改成的数据
def change_data(self, position, data):
# 容错判断
if self.is_empty() or position < 0 or position >= self.length():
print("change_data error")
return
current = self.head
for _ in range(position + 1):
current = current.next
current.data = data
首先进行容错判断,判空以及position的合法性
之后通过for循环将current遍历到要修改节点的位置,直接通过current.data访问节点的data域进行数据的修改
P.12 完整代码(可执行)
python
class Node:
"""创建单链表节点"""
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self):
# 初始化一个头节点,它不包含实际数据,仅作为链表的起始标志
self.head = Node()
# 2.向单向链表的指定位置插入数据
# post 插入的位置 data插入的数据
def insert(self, position, data):
# 容错判断
if position < 0 or position > self.length():
print("insert error")
return
# node新节点
new_node = Node(data)
# 移动伪指针到插入位置的前一个位置
current = self.head
for _ in range(position):
current = current.next
# 插入动作(先连后面,再连前面)
new_node.next = current.next
current.next = new_node
# 3.遍历单向链表
def show(self):
current = self.head
while current.next:
current = current.next
print(current.data, end=' ')
print()
# 4.求单向链表长度的函数
def length(self):
current = self.head
length = 0
while current.next:
current = current.next
length += 1
return length
# 5.删除单向链表中指定位置的数据 post 代表的是删除的位置
def delete_position(self, position):
# 容错判断
if self.is_empty() or position < 0 or position >= self.length():
print("delete_position error")
return
current = self.head
# current走到删除位置的前一个位置
for _ in range(position):
current = current.next
# 删除动作
current.next = current.next.next
# 6.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
def delete_data(self, data):
if self.is_empty():
print("delete_data error")
return
current = self.head
while current.next:
if current.next.data == data:
current.next = current.next.next
else:
current = current.next
# 7.判断单向链表是否为空 1代表空 0代表非空
def is_empty(self):
return self.head.next is None
# 8.修改指定位置的数据 post 被修改的位置 data修改成的数据
def change_data(self, position, data):
# 容错判断
if self.is_empty() or position < 0 or position >= self.length():
print("change_data error")
return
current = self.head
for _ in range(position + 1):
current = current.next
current.data = data
# 9.查找指定数据出现的位置 data被查找的数据 //search 查找
def search_data(self, data):
if self.is_empty():
print("search_data error")
return
current = self.head
position = 0
while current.next:
current = current.next
if current.data == data:
return position
position += 1
return -1
# 10.转置链表
def reverse(self):
# 断开前,保存头节点的下一个节点的地址
current = self.head.next
# 断开链表
self.head.next = None
# 遍历无头单向链表,把无头单向链表的节点头插到有头空链表中
while current:
# 提前将current的下一个节点保存起来
next_node = current.next
# 先连后面,再连前面, 将无头表的节点插入头结点的下一个位置
current.next = self.head.next
self.head.next = current
# 将current移动,指向下一个节点
current = next_node
# 11.清空单向链表
def clear(self):
pass
# endif
if __name__ == '__main__':
link_list = LinkedList()
link_list.insert(0, 999)
link_list.insert(1, 888)
link_list.insert(2, 888)
link_list.show()
link_list.insert(0, 666)
link_list.show()
link_list.insert(1, 777)
link_list.show()
link_list.reverse()
link_list.show()
link_list.delete_position(0)
link_list.show()
link_list.insert(0, 666)
link_list.show()
link_list.delete_data(666)
link_list.show()
link_list.change_data(1,666)
link_list.show()
print(link_list.search_data(777))