单链表操作
一:函数功能
- 链表是否为空
- 链表的长度
- 遍历链表
- 链表头部添加元素
- 链表尾部添加元素
- 链表指定位置添加元素
- 链表删除节点
- 查找节点是否存在
二:代码实现
(一):定义节点类
作用:数据保存在节点中,通过增加节点达到增加数据的目的
class Node:
def __init__(self,elem):
self.elem = elem
# 一开始不知道节点的链接去指向谁,所以,让其值为None
self.next = None
(二):定义链表类
-
定义头节点
思路及图解:
为了能够让第一个节点挂到链表上,需要使用一个头节点指向第一个节点
class LinkList:
def __init__(self,node=None):
self.head = node
-
定义链表是否为空函数
思路及图解:
只需要判断头节点是否为None即可,如下面情况
def is_empty(self):
return self.head == None
-
计算链表的长度
思路及图解:
定义一个计时器,没执行一次next就让计数器加1
特殊情况:空链表情况,此函数适用于空列表情况
def length(self):
# 定义一个计数器
count = 0
# 定义一个游标
cur = self.head
while cur != None:
# 每循环一次,计数器加1
count += 1
# 移动游标
cur = cur.next
return count
-
遍历链表
思路及图解:
思路与计算链表长度类似
def travel(self):
# 定义一个游标
cur = self.head
while cur != None:
print(cur.elem,end=" ")
# 移动游标
cur = cur.next
print(None)
-
列表头部添加元素
思路及图解:
分为两种情况,一种是空列表,一种是非空列表,但两种情况可用同一个函数解决
def add(self,item):
# 构造一个节点
node = Node(item)
# 改变构造节点的next
node.next = self.head
# 改变head的指向
self.head = node
-
链表尾部添加元素(尾插法)
思路及图解:
分为两种情况:一种为非空列表,需要经过循环先找到最后一个元素;一种为空列表,因为空列表无next,如果给空列表进行next程序就会报错,导致程序无法执行,所以要分情况处理
def append(self,item):
# 创建一个新节点
node = Node(item)
# 判断列表是否为空
if self.is_empty():
self.head = node
else:
# 创建一个游标
cur = self.head
# 将新节点的next值指向None
while cur.next != None:
cur = cur.next
cur.next = node
-
指定位置添加元素
思路及图解:
考虑三种情况:第一种是在链表的中间按部位插入,先找到插入位置前面的一个元素,再进行赋值,需要注意的是赋值顺序(即线的连接顺序);第二种是传入的索引超出了链表的最大索引值,超出最大索引值则在尾部进行插入;第三种是传入的索引为负数,当传入的索引值为负数时在头部进行插入
def insert(self,num,item):
if num > (self.length()-1):
self.append(item)
elif num <= 0:
self.add(item)
else:
# 新建一个节点
node = Node(item)
# 定义一个游标
cur = self.head
# 定义一个计数器
count = 0
while count < (num-1):
count += 1
# 注意:注意赋值的先后顺序,如果先为cur.next赋值,那么就会找不到原本的cur.next的值了
cur = cur.next
node.next = cur.next
cur.next = node
-
链表删除指定节点
思路及图解:
考虑三种情况:第一种为删除的节点是首节点;第二种情况为删除的节点是中间节点;第三种情况为删除的节点是尾节点,删除中间节点的函数同样适用于删除尾节点
实现代码
def remove(self,item):
# 定义两个游标
cur = self.head
per_cur = None
# 循环链表
while cur != None:
# 判断要删除的节点
if cur.elem == item:
# 如果是头节点则执行以下赋值
if cur == self.head:
self.head = cur.next
# 不是头节点则执行以下赋值
else:
per_cur.next = cur.next
else:
# 先将cur的游标位置让给per_cur,然后再让cur游标向下移
动
# 注:这里要注意赋值的顺序不能变,不然per_cur游标指>向的就不是cur后面的节点了
per_cur = cur
cur = cur.next
查找节点是否存在
思路及图解
通过判断节点的值来判定节点是否存在
def search(self,item):
# 定义一个游标
cur = self.head
# 循环链表
while cur != None:
# 判断节点的值与输入值是否相等
if cur.elem == item:
# 如果相等返回True
return True
else:
# 如果不相等则比较下一个节点
cur = cur.next
# 推出循环则代表没有相等的值,返回False
return False
三:整体代码(无注释)及效果演示
class Node():
def __init__(self,elem):
self.elem = elem
self.next = None
class LinkList():
def __init__(self,node=None):
self.head = node
def is_empty(self):
return self.head == None
def length(self):
count = 0
cur = self.head
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
cur = self.head
while cur != None:
print(cur.elem,end=" ")
cur = cur.next
print()
def add(self,item):
node = Node(item)
node.next = self.head
self.head = node
def append(self,item):
node = Node(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(self,num,item):
if num > (self.length()-1):
self.append(item)
elif num <= 0:
self.add(item)
else:
node = Node(item)
cur = self.head
count = 0
while count < (num-1):
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
def remove(self,item):
cur = self.head
per_cur = None
while cur != None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
else:
per_cur.next = cur.next
break
else:
per_cur = cur
cur = cur.next
def search(self,item):
cur = self.head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == "__main__":
link = LinkList()
print(link.is_empty())
print(link.length())
link.travel()
link.append(100)
link.append(200)
link.add(0)
link.insert(1,900)
link.insert(8,300)
link.insert(-2,-1)
link.travel()
print(link.search(2))
print(link.search(300))
link.remove(300)
link.travel()
输出结果
True
0
-1 0 900 100 200 300
False
True
-1 0 900 100 200