双向循环链表
每个结点有两个指针域,分别指向前驱结点和后继结点,尾结点的后继指针指向头结点,头结点的前驱指针指向尾结点。整体形成一个双向连通的环。
创建一个结点类:
class Node(object):
"""结点类"""
def __init__(self, data):
self.data = data
self.pre = None
self.next = None
创建一个创建双向循环链表的类:
class CreateDoubleCircularLinkedList(object):
"""创建双向循环链表"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断双向循环链表是否为空"""
return self.head is None
def length(self):
"""获取双向循环链表的长度"""
cur = self.head
count = 0
if self.is_empty():
return 0
while cur is not None:
count += 1
if cur.next == self.head:
break
else:
cur = cur.next
return count
def traversal(self):
"""遍历双向循环链表"""
if self.is_empty():
print("链表为空")
return
cur = self.head
while cur is not None:
print(cur.data)
if cur.next == self.head:
break
else:
cur = cur.next
def search_node(self, data):
"""查找指定结点是否存在"""
cur = self.head
while cur is not None:
if cur.data == data:
return True
# 如果已经查到尾部,则查找结束
elif cur.next == self.head:
return False
else:
cur = cur.next
return False
在头部添加结点:
无论是头部插入、尾部插入还是中间插入,都需要注意的是:
- 每个结点有两个指针域,都需要设置正确的指向
- 头结点要和尾结点相连
需要修改的地方:
- 连接尾结点和新结点
- 连接新结点和头结点
- 将头结点的称号给新结点
def add_first(self, data):
"""在头部添加结点"""
node = Node(data)
cur = self.head
if self.is_empty():
self.head = node
node.next = node
else:
while cur.next != self.head:
cur = cur.next
# 尾结点和新结点互指
cur.next = node
node.pre = cur
# 新结点和头结点互指
node.next = self.head
self.head.pre = node
# 将头指针给新结点
self.head = node
在尾部添加结点:
- 连接尾结点和新结点
- 连接新结点和头结点
def add_last(self, data):
"""在尾部添加结点"""
node = Node(data)
cur = self.head
if self.is_empty():
self.head = node
node.next = node
else:
while cur.next != self.head:
cur = cur.next
# 连接尾部结点和新结点
cur.next = node
node.pre = cur
# 连接新结点和头结点
node.next = self.head
self.head.pre = node
在指定位置添加结点:
- 连接前驱结点和新结点
- 连接后继结点和新结点
(这样,原来的前驱结点和后继结点就断开了,中间插入进来一个新结点)
def insert_node(self, index, data):
""""在指定位置添加结点"""
node = Node(data)
if index < 0 or index > self.length():
return False
elif index == 0:
self.add_first(data)
elif index == self.length():
self.add_last(data)
else:
cur = self.head
pres = None
count = 0
# 指针移动到要添加的位置
while count < index:
pres = cur
cur = cur.next
count += 1
# 连接前驱结点和新结点
cur.pre.next = node
node.pre = cur.pre
# 连接后继结点和新结点
node.next = cur
cur.pre = node
删除结点:
就是将循环链表和双向链表需要考虑的地方都考虑到,然后结合一下就可以,这里只是将删除头结点和尾结点单独写出来。(注意只有一个头结点的时候)
def remove_first(self):
"""删除头结点"""
cur = self.head
if self.is_empty():
return False
# 如果只有头结点一个
elif self.head.next is self.head:
self.head = None
return True
while cur.next != self.head:
cur = cur.next
# 连接尾结点和新的头结点
cur.next = self.head.next
self.head.next.pre = cur
# 将头指针给新的头结点
self.head = self.head.next
def remove_last(self):
"""删除尾结点"""
cur = self.head
if self.is_empty():
return False
# 如果只有头结点一个
elif self.head.next is self.head:
self.head = None
return True
while cur.next != self.head:
cur = cur.next
# 连接新的尾结点和头结点
cur.pre.next = self.head
self.head.pre = cur.pre
def remove_node(self, data):
"""删除指定结点"""
cur = self.head
if data == self.head.data:
self.remove_first()
else:
while cur.data != data:
cur = cur.next
# 如果是尾结点
if cur.next == self.head:
self.remove_last()
else:
# 连接指定结点的前驱结点和后继结点
cur.pre.next = cur.next
cur.next.pre = cur.pre
链表置空:
逐渐从链表中删除结点,知道链表为空为止
def set_empty(self):
"""将双向循环链表置空"""
while self.is_empty() is False:
self.remove_last()
主函数测试:
if __name__ == '__main__':
lists = CreateDoubleCircularLinkedList()
lists.add_first(2)
lists.add_first(1)
lists.add_last(4)
lists.insert_node(2, 3)
print("是否为空:", lists.is_empty())
print("获取长度:", lists.length())
print("当前结点是否存在:", lists.search_node(2))
lists.traversal()
lists.remove_node(3)
print("删除之后遍历")
lists.traversal()
lists.set_empty()
print("置空之后的遍历")
lists.traversal()
测试结果截图:
完整代码:
class Node(object):
"""结点类"""
def __init__(self, data):
self.data = data
self.pre = None
self.next = None
class CreateDoubleCircularLinkedList(object):
"""创建双向循环链表"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断双向循环链表是否为空"""
return self.head is None
def length(self):
"""获取双向循环链表的长度"""
cur = self.head
count = 0
if self.is_empty():
return 0
while cur is not None:
count += 1
if cur.next == self.head:
break
else:
cur = cur.next
return count
def traversal(self):
"""遍历双向循环链表"""
if self.is_empty():
print("链表为空")
return
cur = self.head
while cur is not None:
print(cur.data)
if cur.next == self.head:
break
else:
cur = cur.next
def search_node(self, data):
"""查找指定结点是否存在"""
cur = self.head
while cur is not None:
if cur.data == data:
return True
# 如果已经查到尾部,则查找结束
elif cur.next == self.head:
return False
else:
cur = cur.next
return False
def set_empty(self):
"""将双向循环链表置空"""
while self.is_empty() is False:
self.remove_last()
def add_first(self, data):
"""在头部添加结点"""
node = Node(data)
cur = self.head
if self.is_empty():
self.head = node
node.next = node
else:
while cur.next != self.head:
cur = cur.next
# 尾结点和新结点互指
cur.next = node
node.pre = cur
# 新结点和头结点互指
node.next = self.head
self.head.pre = node
# 将头指针给新结点
self.head = node
def add_last(self, data):
"""在尾部添加结点"""
node = Node(data)
cur = self.head
if self.is_empty():
self.head = node
node.next = node
else:
while cur.next != self.head:
cur = cur.next
# 连接尾部结点和新结点
cur.next = node
node.pre = cur
# 连接新结点和头结点
node.next = self.head
self.head.pre = node
def insert_node(self, index, data):
""""在指定位置添加结点"""
node = Node(data)
if index < 0 or index > self.length():
return False
elif index == 0:
self.add_first(data)
elif index == self.length():
self.add_last(data)
else:
cur = self.head
pres = None
count = 0
# 指针移动到要添加的位置
while count < index:
pres = cur
cur = cur.next
count += 1
# 连接前驱结点和新结点
cur.pre.next = node
node.pre = cur.pre
# 连接后继结点和新结点
node.next = cur
cur.pre = node
def remove_first(self):
"""删除头结点"""
cur = self.head
if self.is_empty():
return False
# 如果只有头结点一个
elif self.head.next is self.head:
self.head = None
return True
while cur.next != self.head:
cur = cur.next
# 连接尾结点和新的头结点
cur.next = self.head.next
self.head.next.pre = cur
# 将头指针给新的头结点
self.head = self.head.next
def remove_last(self):
"""删除尾结点"""
cur = self.head
if self.is_empty():
return False
# 如果只有头结点一个
elif self.head.next is self.head:
self.head = None
return True
while cur.next != self.head:
cur = cur.next
# 连接新的尾结点和头结点
cur.pre.next = self.head
self.head.pre = cur.pre
def remove_node(self, data):
"""删除指定结点"""
cur = self.head
if data == self.head.data:
self.remove_first()
else:
while cur.data != data:
cur = cur.next
# 如果是尾结点
if cur.next == self.head:
self.remove_last()
else:
# 连接指定结点的前驱结点和后继结点
cur.pre.next = cur.next
cur.next.pre = cur.pre
if __name__ == '__main__':
lists = CreateDoubleCircularLinkedList()
lists.add_first(2)
lists.add_first(1)
lists.add_last(4)
lists.insert_node(2, 3)
print("是否为空:", lists.is_empty())
print("获取长度:", lists.length())
print("当前结点是否存在:", lists.search_node(2))
lists.traversal()
lists.remove_node(3)
print("删除之后遍历")
lists.traversal()
lists.set_empty()
print("置空之后的遍历")
lists.traversal()
因为双向循环链表既双向通,又整体循环,所以无论在任何位置,都能遍历整个链表,非常灵活。