链表,顾名思义,是用链子串起来的列表(好吧,这知识把这两个字拆开了)。重点在于“链”字,链表中每一个元素被称为结点,每一个节点包括两个域:数据域和地址域。数据域用来存放本身的数据,地址域用来存放下一个结点或上一个节点的内存地址。操作链表的时候通过当前结点的地址域寻找下一个结点。只能顺序遍历,不能像列表一样可以随机遍历。
一。单向链表---每一个node存储的内存地址不连续,由前一个node的指针找到下一个node的内存地址。
# 单向链表:每一个node存储的内存地址不连续,由前一个node的指针找到下一个node的内存地址。
class Node:
"""创建节点"""
def __init__(self, data=None):
""" 初始化
添加节点本身数据
添加指向下一个节点的地址
"""
self.data = data
self.next = None
def get_data(self):
"""返回结点本身的数据"""
return self.data
def get_next(self):
"""得到下一个结点的地址"""
return self.next
def set_data(self, new_data):
"""修改结点本身的数据"""
self.data = new_data
def set_next(self, new_next):
"""修改指向下一个结点的地址"""
self.next = new_next
class UnorderList:
""" 无序链表:
本例采用的是单向链表,链表中每一个节点由两部分组成,分别是节点本身数据域和指向下一个节点地址域。
单向链表的方法包括添加、删除、搜索、判断是否为空、遍历等
在无序链表中,新结点对于列表中已存在的其他结点的特定位置不重要。新结点可以保存在任何地方。
"""
def __init__(self):
"""初始化"""
self.head = None # 头结点
def is_empty(self):
"""判断链表是否为空"""
return True if self.head == None else False
def add(self, data):
"""添加新节点"""
temp = Node(data) # 创建新结点
temp.set_next(self.head) # 将新结点链接之前的list
self.head = temp # 将新结点设为head
def search(self, data):
"""查询链表里是否存在data这个结点数据"""
current = self.head
found = False
while current and not found:
if current.get_data() == data:
found = True
else:
current = current.get_next()
return found
def delete(self, data):
"""删除链表中数据为data的结点"""
current = self.head
previous = None
found = False
while current and not found:
if current.get_data() == data:
found = True
else:
previous = current
current = current.get_next()
if not current:
print(f"没有找到数据{data}")
return False
elif not previous:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
def show(self):
"""输出链表的各个节点数据,返回链表长度"""
current = self.head
count = 0
while current:
print(current.data)
count += 1
current = current.next
return count
class OrderList:
"""有序链表:
与无序链表之间的区别在于添加新节点的时候,
不再是盲目的添加在表头,而是与现有链表节点的数据进行比较,
然后添加在合适的位置
"""
def __init__(self):
"""初始化链表"""
self.head = None
def is_empty(self):
"""判断链表是否为空"""
return True if self.head == None else False
def add(self, data):
"""添加新节点,并将节点数据进行比较排序,本例是递升有序链表"""
current = self.head
previous = None
stop = False
while current and not stop:
if type(current.get_data()) == type(data) and current.get_data() > data:
stop = True
else:
previous = current
current = current.get_next()
temp = Node(data)
if not previous:
temp.set_next(self.head)
self.head = temp
else:
temp.set_next(current)
previous.set_next(temp)
def search(self, data):
"""查询链表里是否存在data这个结点数据"""
current = self.head
found = False
stop = False
while current and not found and not stop:
if type(current.get_data()) == type(data):
if current.get_data() == data:
found = True
elif current.get_data() > data:
stop = True
current = current.next
return found
def delete(self, data):
"""删除链表中数据为data的结点"""
current = self.head
previous = None
found = False
while current and not found:
if current.get_data() == data:
found = True
else:
previous = current
current = current.get_next()
if not current:
print(f"没有找到数据{data}")
return False
elif not previous:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
def show(self):
"""输出链表的各个节点数据,返回链表长度"""
current = self.head
count = 0
while current:
print(current.data)
count += 1
current = current.next
return count
def main():
"""测试"""
link_unorder = UnorderList()
link_unorder.add(3)
link_unorder.show()
link_unorder.add('aaa')
link_unorder.show()
print(link_unorder.is_empty())
print(link_unorder.search(3))
print(link_unorder.search('aaa'))
link_unorder.delete(2)
link_unorder.delete(3)
print(link_unorder.show())
print("以下是有序链表的测试")
link_order = OrderList()
link_order.add(3)
link_order.show()
link_order.add(6)
link_order.show()
link_order.add(1)
link_order.show()
link_order.add('aaa')
link_order.add('daa')
link_order.add('baa')
link_order.show()
print(link_order.is_empty())
print(link_order.search(3))
print(link_order.search('aaa'))
link_order.delete(2)
link_order.delete(3)
link_order.delete('baa')
print(link_order.show())
if __name__ == '__main__':
main()
二、双向链表------每一个节点既指向前一个节点,又指向后一个节点
class DoubleNode:
"""创建节点"""
def __init__(self, data=None):
"""初始化"""
self.data = data
self.next = None
self.prev = None
def get_data(self):
"""返回结点本身的数据"""
return self.data
def set_data(self, new_data):
"""修改结点本身的数据"""
self.data = new_data
def get_next(self):
"""得到下一个结点的地址"""
return self.next
def get_previous(self):
"""得到上一个结点的地址"""
return self.prev
def set_next(self, new_next):
"""修改指向下一个结点的地址"""
self.next = new_next
def set_previous(self, new_prev):
"""修改指向上一个结点的地址"""
self.prev = new_prev
class DoubleLinkedList():
""" 双向链表:
与传统的单向链表区别在于,双向链表的每一个节点由三部分组成,分别是节点本身数据域,指向前一个节点地址域,指向后一个结点地址域。我们既可以从表头和表尾两个方向进行操作,每个方向可以看做是一个单向链表。
双向链表与单向链表的方法大致相同。都包括添加、删除、搜索、判断是否为空、遍历等
"""
def __init__(self):
""" 初始化双向链表
本例的初始化是初始化两个节点,一个头结点,一个尾结点,这两个节点可以充当哨兵的作用。这样做的好处是添加新节点的时候可以不用判断这个节点是否为第一个节点,删除节点的时候也可以变得简单。不好的地方是多余了两个节点的内存。
"""
head = DoubleNode()
tail = DoubleNode()
self.head = head
self.tail = tail
self.head.next = self.tail
self.tail.prev = self.head
def search(self, data):
""" 查找数据域为data的结点:
若成功找到该节点,则返回第一个数据域为data的结点对象。
若查找失败则返回None。
"""
node = self.head.next
while node != self.tail:
if node.data == data:
return node
node = node.next
return None
def size(self):
"""获取链表的长度"""
length = 0
node = self.head.next
while node != self.tail:
length += 1
node = node.next
return length
def add(self, data):
""" 添加节点:
因为初始化链表的时候就创建了头尾节点,所以新增节点统一看做中间节点插入便可。
"""
node = DoubleNode(data)
prev_node = self.tail.prev
prev_node.next = node
node.prev = prev_node
self.tail.prev = node
node.next = self.tail
return 'OK'
def delete(self, data):
""" 删除数据域为data的结点"""
node = self.search(data)
if node:
prev_node = node.prev
next_node = node.next
prev_node.next = next_node
next_node.prev = prev_node
return True
else:
return False
def show(self):
""" 遍历双向链表:
可以正向遍历:以头结点为起始结点(本例)。
也可以反向遍历:以尾结点为起始结点
"""
node = self.head.next
while node != self.tail:
print(node.data)
node = node.next
def is_empty(self):
return self.head.next == self.tail
def main():
"""测试"""
double_link = DoubleLinkedList()
print(double_link.is_empty())
double_link.add('aaaa')
double_link.add(4)
double_link.show()
print(double_link.search('aaaa'))
print(double_link.search(3))
print(double_link.size())
print(double_link.delete('bbb'))
print(double_link.delete(4))
double_link.show()
if __name__ == '__main__':
main()