Python数据结构与算法系列:单链表
单链表
1.单链表的结构
链表是一种由一系列节点组成的线性结构,其中每个节点由data域和next域组成,data域用于存储该节点的数据,next域用于存储下一个节点的地址。其在内存中的存储可以是连续的也可以是不连续的。
单链表结构示意图:
2.单链表的基础操作
- isEmpty(): 判断链表是否为空
- size(): 返回链表中元素个数
- insert() : 向链表尾插入一个元素
- insertByOrder(): 按顺序向链表中插入元素
- update(): 更新某一节点信息
- delete(): 删除某一节点
- search(): 查找某个节点
- showList(): 打印链表所有元素
Note:对于单链表而言,在进行一系列操作时,需要注意几种边界情况:
1)链表为空
2)链表中只有一个元素
3)常规情形
3. 单链表的python实现
class Node(object):
'''节点的定义'''
def __init__(self,id,data,next_=None):
self.id =id
self.data = data
self.next = next_
def __str__(self):
return "Node[id= "+ str(self.id) +",data= "+str(self.data)+"]"
class SingleLinkedList(object):
def __init__(self):
self.head = Node(0,"") # 链表头节点,不存储任何信息
self.count = 0 # 记录链表中元素个数,初始化为0
def isEmpty(self):
'''判断链表是否为空,若为空,则返回True,
反之 若不为空,返回False'''
return self.count == 0
@property
def size(self):
'''返回链表中所有元素个数'''
return self.count
def insert(self,newNode):
'''在链表尾部插入元素'''
temp = self.head # 设置临时变量temp指向链表头节点
while True:
if temp.next is None: # 找到链表尾部节点
break
temp = temp.next # 临时变量temp后移
temp.next = newNode # 将新节点插入链表尾部
self.count += 1
def insertByOrder(self,newNode):
'''按照节点id顺序插入'''
temp = self.head
flag = False # 标记待插入节点id是否存在,若存在,则提示重复,不能插入
while True:
if temp.next is None: # 说明已经遍历到链表尾
break
if temp.next.id > newNode.id: # 找到合适位置
break
if temp.next.id == newNode.id: # 重复
flag = True
break
temp = temp.next
if flag:
print("节点%d已存在"%newNode.id)
else:
newNode.next = temp.next # 将新节点的next 指向当前节点的next
temp.next = newNode # 将当前节点的next指向新节点
self.count += 1
def update(self,newNode):
'''根据id修改某一节点的数据'''
temp = self.head.next # 临时变量temp指向第一个存放数据的节点
flag = False # 标记是否存在该节点
if self.isEmpty():
print("链表为空")
return
while True:
if temp is None: # 已遍历到链表尾部
break
if temp.id == newNode.id: # 表明已找到待修改节点
flag = True
break
temp = temp.next
if flag:
temp.data = newNode.data
else:
print("节点%d不存在,无法修改"%newNode.id)
def delete(self,id):
'''根据id删除对应节点
此时不能直接找到待删除节点,而是找到待删除节点的前一个节点'''
temp = self.head
flag = False
while True:
if temp.next is None:
break
if temp.next.id == id:
flag = True
break
temp = temp.next
if flag:
temp.next = temp.next.next
self.count -= 1
else:
print("待删除节点%d不存在"%id)
def search(self,id):
'''根据id查找节点,若节点存在,返回True,否则返回False'''
if self.isEmpty():
return False
temp = self.head
flag = False
while True:
if temp.next is None:
break
if temp.next.id == id:
flag = True
break
temp = temp.next
return flag
def showList(self):
if self.isEmpty():
print("空链表!")
return
temp = self.head.next
while True:
if temp is None:
break
print(temp)
temp = temp.next
测试代码:
def main():
node1 = Node(1,"A")
node2 = Node(2,"B")
node3 = Node(3,"C")
node4 = Node(5,"E")
lst = SingleLinkedList()
print(lst.size)
print(lst.isEmpty())
print(" ===== 向链表尾部插入 =====")
lst.insert(node1)
lst.insert(node2)
lst.insert(node3)
lst.insert(node4)
print(lst.size)
lst.showList()
print(" ===== id顺序插入 =====")
node5 = Node(4,"D")
lst.insertByOrder(node5)
print(lst.size)
lst.showList()
print(" ===== 修改节点数据 =====")
node6 = Node(4,"F")
lst.update(node6)
lst.showList()
print(" ===== 删除节点 =====")
lst.delete(1)
print(lst.size)
lst.showList()
print(" ===== 查找节点 =====")
print(lst.search(1))
print(lst.search(4))
print(lst.search(7))
if __name__ == "__main__":
main()
测试结果: