概念
单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
节点包含两个域:元素域和链接域(下一个节点),尾节点next指向第0个节点,当链表只有一个节点时,自己的next指向自己,基于单链表的基础上,增加考虑首节点和尾节点的情况。
结构
python代码实现
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
class CycleLinkList(object):
def __init__(self):
self.head = None
def is_empty(self):
"""链表是否为空"""
return self.head is None
def length(self):
"""链表长度"""
if self.is_empty():
return 0
cur = self.head
n = 1
while cur.next != self.head:
n += 1
cur = cur.next
# 至此除了尾节点外,所有节点都被数了一次
return n
def travel(self):
"""遍历整个链表"""
if self.is_empty():
return
cur = self.head
while cur.next != self.head:
print(cur.item,end="->")
cur = cur.next
# 至此,cur指向尾节点,cur本身还未被打印
print(cur.item)
def add(self, item):
"""链表头部添加元素"""
node = Node(item)
# 若没有尾节点(链表为空),head指向新节点,新节点next指向自己
if self.is_empty():
self.head = node
node.next = node
else:
# 1 找到尾节点cur
cur = self.head
while cur.next != self.head:
cur = cur.next
# 至此,cur指向尾节点
#2 新节点next指向原首节点
node.next = self.head
#3 head指向新节点
self.head = node
#4 尾节点next指向新节点
cur.next = node
def append(self, item):
"""链表尾部添加元素"""
# 若链表为空,则直接头部添加
if self.is_empty():
self.add(item)
return
# 1 遍历查找尾节cur
cur = self.head
while cur.next != self.head:
cur = cur.next
# 至此cur指向当前链表的尾节点
# 2 cur的next指向新节点
node = Node(item)
cur.next = node
# 3 新节点next指向首节点
node.next = self.head
def insert(self, pos, item):
"""指定位置添加元素"""
if pos <=0 :
self.add(item)
elif pos >= self.length():
self.append(item)
else:
# 1 遍历查找带插入位置的前一个节点cur
cur = self.head
for i in range(pos - 1):
cur = cur.next
# 至此,cur指向的就是带插入位置的前一个节点
# 2 新节点的next指向cur的next
node = Node(item)
node.next = cur.next
# 3 cur的next指向新节点
cur.next = node
def remove(self, item):
"""删除节点"""
if self.is_empty():
return
cur = self.head
pre = None
# 1 遍历查找找到待删节点并记录前一个节点
while cur.next != self.head:
if cur.item == item:
# 2 若有前一个节点,pre的next指向cur的next
if pre is not None:
pre.next = cur.next
else:
# 否则(待删节点是首节点),
# 1)遍历查找尾节点tail
tail = self.head
while tail.next != self.head:
tail = tail.next
# 2) head指向cur的next
self.head = cur.next
# 3) tail的next指向head
tail.next = self.head
return
pre = cur
cur = cur.next
# 至此cur指向尾节点,尾节点还未判断是否是待删节点
# 3 判断尾节点是否是待删节点
if cur.item == item:
# 若有前一个节点,pre的next指向cur的next
if pre is not None:
pre.next = cur.next
# 否则(待删节点是链表唯一节点),head指向None
else:
self.head = None
def search(self, item):
"""查找节点是否存在"""
if self.is_empty():
return False
cur = self.head
while cur.next != self.head:
if cur.item == item:
return True
cur = cur.next
# 至此,除了尾节点外所有节点都找过了,还没找到
# 判断尾节点是否是待查节点
if cur.item == item:
return True
return False
# 测试代码
if __name__ == '__main__':
cl = CycleLinkList()
cl.add(1)
cl.add(2)
cl.add(3)
cl.travel()
# 结果3-2-1-
cl.append("abc")
cl.append("def")
cl.append("ghi")
cl.travel()
# 结果3-2-1-abc-def-ghi-
cl.insert(-1, "xx")
cl.insert(99, "yy")
cl.insert(3, "zz")
cl.travel()
# 结果xx-3-2-zz-1-abc-def-ghi-yy-
cl.remove("xx")
cl.remove("yy")
cl.remove(1)
cl.remove(90)
cl.travel()
# 结果3-2-zz-abc-def-ghi-
print(cl.search(3))
# 结果True
print(cl.search("zz"))
# 结果True
print(cl.search(380))
# 结果False
复杂度
循环链表头部添加O(n),循环链表尾部添加O(n),循环链表中间位置添加O(n),循环链表删除O(n)。