单向循环链表
循环链表
循环链表是一种特殊的单链表。实际上,循环链表也很简单。它跟单链表唯一的区别就在尾结点。我们知道,单链表的尾结点指针指向空地址,表示这就是最后的结点了。而循环链表的尾结点指针是指向链表的头结点。从我画的循环链表图中,你应该可以看出来,它像一个环一样首尾相连,所以叫作“循环”链表。
操作
is_empty() 判断链表是否为空
length() 返回链表的长度
travel() 遍历
add(item) 在头部添加一个节点
append(item) 在尾部添加一个节点
insert(pos, item) 在指定位置pos添加节点
remove(item) 删除一个节点
search(item) 查找节点是否存在
其代码实现
class Node(object):
'''设置节点'''
def __init__(self,item):
self.item = item # 节点的数据区
self.next = None # 节点的链接区
class SinCycLinkList(object):
'''单项循环节点'''
def __init__(self,node = None):
self.head = node # 设置首节点
if node:
node.next = node
def is_empty(self):
"""判断链表是否为空"""
if self.head == None:
return True
return False
def length(self):
"""返回链表的长度"""
cur = self.head # 设置游标cur指向头节点
count = 1
if self.is_empty(): # 判断链表是否为空
return 0
else: # 链表不为空时
while cur.next!= self.head: # 将游标移动到最后一个节点处,注意这里设置的是count= 1,是因为循环的时候游标在最后一个指向
count += 1
cur = cur.next
return count # 返回count
def travel(self):
"""遍历链表"""
if self.is_empty(): # 判空
return None
else: # 当链表不为空时
cur = self.head
while cur.next != self.head:
print(cur.item,end = ' ')
cur = cur.next # 这里循环到最后一个节点处
print(cur.item) # 打印最后一个节点的数据区
def add(self, item):
"""链表头部添加元素"""
node = Node(item) # 创建新节点
if self.is_empty(): # 判空,如果为空
self.head = node # 将新节点赋值给头节点
node.next = self.head # 由于是单向循环链表,构成循环
else: # 如果不为空
cur = self.head # 将链表指向头节点
while cur.next != self.head:
cur = cur.next # 将节点循环到最后一个节点处
node.next = self.head # 将原来的头节点赋值给新节点的链接区
self.head = node # 将新节点赋值给头节点
cur.next = node # 新头节点和尾节点构成循环
def append(self, item):
"""链表尾部添加元素"""
node = Node(item) # 创建新节点
if self.is_empty(): # 判空
self.add(item) # 如果为空,就给头部添加
else: # 如果不为空时
cur = self.head # 设置cur游标指向头节点
while cur.next != self.head:
cur = cur.next # 循环到最后一个节点处
node.next = self.head # 将头节点赋值给新节点的链接区
cur.next = node # 将新节点赋值给原尾节点的链接区
def insert(self, pos, item):
"""指定位置添加元素"""
if pos <= 0: # pos 为要添加到的位置,这里和单链表一样,按照坐标轴的顺序,当插入的位置小于0时,就默认判断给第一位添加
self.add(item)
elif pos > self.length() - 1: # # 当插入的位置大于链表长度时,默认给链表最后一位添加
self.append(item)
else: # 当添加的位置在链表长度之内时
node = Node(item) # 创建新节点
pre = self.head # pre为要添加位置的上一个节点,设置初始值为None
count = 0
while count < pos - 1:
count += 1
pre = pre.next # 将pre循环到要添加位置的上一个节点处
node.next = pre.next # 将pre节点的链接区赋值给新节点的链接区
pre.next = node # 将新节点指向pre的链接区
def search(self, item):
"""查找节点是否存在"""
if self.is_empty():# 判空
return False
else:
cur = self.head # 设置游标为头节点
while cur.next != self.head:
if cur.item == item: # 判断要查找的数据与节点数据区比较
return True
else:
cur = cur.next # 循环节点
if cur.item == item: # 上面循环指向完之后游标指向尾节点
return True
return False
def remove(self, item):
"""删除节点"""
if self.is_empty(): # 判空
return
cur = self.head # 设置游标
pre = None # 设置要移除节点的上一个节点
# 头节点是要删除的
if cur.item == item:
if cur.next != self.head: # 当链表长度不为1时
while cur.next != self.head:
cur = cur.next # 循环到最后一个节点
cur.next = self.head.next # 将头节点的链接区指向最后一个节点的链接区,构成循环
self.head = cur.next # 将尾节点的链接区指向首节点
else: # 头节点不是要删除的,这里和单链表一样
while cur.next != self.head:
if cur.next == item :
pre.next = cur.next
else:
pre = cur
cur = cur.next
if cur.item == item:# 最后循环到最后一个节点处,比较尾节点的数据区与要查找的数据
pre.next = cur.next
在这里说明一下,只要是要循环到尾节点的操作的函数内,都要先判空,而且还要注意循环到尾节点处,尾节点的数据区还没有判断