循环链表就是最后一个结点的指针域指向头结点,整个链表形成一个环。
class Node(object):
"""创建一个结点类"""
def __init__(self, data):
self.data = data
self.next = None
接下来的一些操作循环链表的函数,都将写在这个类中
class create_circular_linked_list(object):
"""创建一个创建循环链表的类"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断循环链表是否为空"""
return self.head is None
大体流程:
def length(self):
"""获取循环链表的长度"""
cur = self.head
count = 0
while cur is not None:
count += 1
# 如果当前结点的下一个结点是头结点,说明这个结点就是尾结点
# 如果不是,就将指针向后移动一个
if cur.next == self.head:
break
else:
cur = cur.next
return count
为什么要考虑链表为空的情况?
答:如果直接就需要使用cur.next,这种情况就需要考虑链表为空的情况。
因为如果链表为空时,是没有.next属性的,.next属性是结点的属性,空链表没有结点,所以需要考虑链表为空的情况。
def travel(self):
"""遍历链表"""
if self.is_empty():
return
cur = self.head
print(cur.data)
while cur.next != self.head:
cur = cur.next
print(cur.data)
如果链表为空的情况:添加的结点就是头结点,头结点的后继结点还是头结点
如果链表不为空的情况:
def add_first(self, data):
"""在头部添加结点"""
node = Node(data)
if self.is_empty():
self.head = node
node.next = self.head
else:
cur = self.head
# 将指针移动到尾部结点
while cur.next is not self.head:
cur = cur.next
# 尾部结点指向新节点
cur.next = node
# 新结点指向原来的头结点
node.next = self.head
# 再将头结点的称号给新结点
self.head = node
如果链表为空的情况:添加的结点就是头结点,头结点的后继结点还是头结点
如果链表不为空的情况:
(不知道你有没有发现,循环链表的头插法和尾插法很相似,只差最后一行代码,可以思考一下这是为什么)
def add_last(self, data):
"""在尾部添加结点"""
node = Node(data)
if self.is_empty():
self.head = node
node.next = self.head
else:
cur = self.head
# 将指针移动到尾部
while cur.next is not self.head:
cur = cur.next
# 尾部结点指向新结点
cur.next = node
# 新结点指向头结点
node.next = self.head
三种情况:
1、插入出错:索引位置不在链表长度范围之内
2、插入头部:直接调用头插法的函数
3、插入中间:
(当链表为空时,我们只能插入到第0个位置,也就是调用头插法即可,当链表不为空时,即可正常插入)
def insert_node(self, index, data):
"""在指定位置插入结点"""
node = Node(data)
if index < 0 or index > self.length():
print("插入位置错误")
return False
elif index == 0:
self.add_first(data)
elif index == 0:
self.add_last()
else:
cur = self.head
pre = None # pre为当前指针所指向结点的前一个结点
count = 0
# 将指针移动到要插入的位置
while count < index:
pre = cur
cur = cur.next
count += 1
pre.next = node
node.next = cur
1、链表为空的情况:没有结点可删除,直接返回
2、链表不为空的情况:
1、要删除的结点就是头结点:
1、指针移到尾部
2、尾结点指向头结点的下一个(跳过头结点)
3、将头结点的称号给头结点的下一个(让原头结点的下一个,成为新的头结点)
2、要删除的结点不是头结点
1、移动到要删除结点的位置
2、将要删除结点(cur)的前驱节点(pre)指向要删除结点(cur)的后继结点(如下图所示,也就是跳过了中间要删除的结点,以达到删除的目的)
def remove_node(self, data):
"""删除指定结点"""
if self.is_empty():
return
# 如果要删除的结点就是头结点
elif data == self.head.data:
# 如果链表只有一个头结点
if self.head.next is self.head:
self.head = None
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
cur.next = self.head.next
self.head = self.head.next
else:
cur = self.head
pre = None
# 移动到要删除结点的位置
while cur.data != data:
# 如果没找到
if cur.next == self.head:
return
pre = cur
cur = cur.next
# 将要删除的结点的前驱结点指向后继结点,这样就跳过了中间的结点
pre.next = cur.next
(因为我们在while中直接判断当前结点是否为空,所以不需要再单独考虑链表是否为空的情况了)
然后我们需要考虑三种情况:
def is_exist(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
if __name__ == '__main__':
lists = create_circular_linked_list()
lists.add_last(2)
lists.add_first(1)
lists.add_first(0)
lists.add_last(3)
lists.insert_node(2, 8)
lists.travel()
print("链表长度:", lists.length())
lists.remove_node(8)
lists.travel()
print(lists.is_exist(2))
class Node(object):
"""创建一个结点类"""
def __init__(self, data):
self.data = data
self.next = None
class create_circular_linked_list(object):
"""创建一个创建循环链表的类"""
def __init__(self):
self.head = None
def is_empty(self):
"""判断循环链表是否为空"""
return self.head is None
def length(self):
"""获取循环链表的长度"""
cur = self.head
count = 0
while cur is not None:
count += 1
# 如果当前结点的下一个结点是头结点,说明这个结点就是尾结点
# 如果不是,就将指针向后移动一个
if cur.next == self.head:
break
else:
cur = cur.next
return count
def add_first(self, data):
"""在头部添加结点"""
node = Node(data)
if self.is_empty():
self.head = node
node.next = self.head
else:
cur = self.head
# 将指针移动到尾部结点
while cur.next is not self.head:
cur = cur.next
# 尾部结点指向新节点
cur.next = node
# 新结点指向原来的头结点
node.next = self.head
# 再将头结点的称号给新结点
self.head = node
def add_last(self, data):
"""在尾部添加结点"""
node = Node(data)
if self.is_empty():
self.head = node
node.next = self.head
else:
cur = self.head
# 将指针移动到尾部
while cur.next is not self.head:
cur = cur.next
# 尾部结点指向新结点
cur.next = node
# 新结点指向头结点
node.next = self.head
def insert_node(self, index, data):
"""在指定位置插入结点"""
node = Node(data)
if index < 0 or index > self.length():
print("插入位置错误")
return False
elif index == 0:
self.add_first(data)
else:
cur = self.head
pre = None # pre为当前指针所指向结点的前一个结点
count = 0
# 将指针移动到要插入的位置
while count < index:
pre = cur
cur = cur.next
count += 1
pre.next = node
node.next = cur
def remove_node(self, data):
"""删除指定结点"""
if self.is_empty():
return
# 如果要删除的结点就是头结点
elif data == self.head.data:
# 如果链表只有一个头结点
if self.head.next is self.head:
self.head = None
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
cur.next = self.head.next
self.head = self.head.next
else:
cur = self.head
pre = None
# 移动到要删除结点的位置
while cur.data != data:
# 如果没找到
if cur.next == self.head:
return
pre = cur
cur = cur.next
# 将要删除的结点的前驱结点指向后继结点,这样就跳过了中间的结点
pre.next = cur.next
def travel(self):
"""遍历链表"""
if self.is_empty():
return
cur = self.head
print(cur.data)
while cur.next != self.head:
cur = cur.next
print(cur.data)
def is_exist(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
if __name__ == '__main__':
lists = create_circular_linked_list()
lists.add_last(2)
lists.remove_node(2)
print(lists.is_empty())
lists.add_first(1)
lists.add_first(0)
lists.add_last(3)
lists.insert_node(2, 8)
lists.travel()
print("链表长度:", lists.length())
lists.remove_node(8)
lists.travel()
print(lists.is_exist(2))
因为循环链表是一个闭合的环,所以我们遍历的时候,从链表的任意一个位置开始遍历都可以,而要注意的是设定好遍历结束的条件。