单项循环链表 : 单链表的一个特殊形式就是单向循环链表,链表中最后一个节点的next不再为None,而是指向当前链表的头节点 单向循环链表的结构
# 单向循环链表
# 链表中最后一个节点的next不再为None,
# 而是指向当前链表的头节点
# 实例化结点
class Node(object):
def __init__(self,data):
self.data = data
self.next = None # 指针域next先默认等于none
# 单向循环链表
class Singlecyclink(object):
# 初始化
def __init__(self,node=None):
self.__head = node
# 链表的最后一个结点node指向链表头结点
# 第一次创建结点时,先解决第一个结点node.next的指向问题
# if语句是针对循环链表中只有一个节点的情况
# 如果是通过删除方法使链表只剩下一个节点是不会进入init方法的,
# 因为init方法在实例化的时候就直接执行了
if node:
node.next = node # 此时链表只有一个值,链表末尾结点next指向其本身
# 判断为空
def is_empty(self):
return self.__head == None
# 长度判断
# 指针指到尾部,
# 同时有计数器进行计数,
# 单向循环链表的尾部指向头部,
# 如果等于头部,说明走到最后
def length(self):
# 判断是否为空
if self.is_empty():
return 0
else:
# 当指针走到尾部的时候,
# while判断为假,
# 无法进入循环使计数器加1,
# 相当于没有计算尾部结点,因此从1开始计数
count = 1
cur = self.__head
# 当指针next域不是指向head时,
# 进入循环,计数器计数,指针跳转
while cur.next is not self.__head:
cur = cur.next
count += 1
# 当指针走到尾部的时候,
# while判断为假,
# 无法进入循环使计数器加1,
# 相当于没有计算尾部结点
return count
# 打印
# 如果链表为空,不需要打印,
# 不为空时,需要实例化指针cur,
# 帮助移动到尾部,同时把尾部打印出来
# 当移动到尾部时,不能进入while循环语句(或者说退出循环),
# 因此最后需要单独打印一下cur
def travel(self):
# 判断是否为空
if self.is_empty():
print('空链表')
else:
cur = self.__head
while cur.next is not self.__head:
print(cur.data,end=' ')
# 如果忘记过程跟踪,将一直打印第一个值
cur = cur.next
# 当移动到尾部时,
# 不能进入while循环语句(或者说退出循环),
# 因此最后需要单独打印一下cur
print(cur.data)
print(end='\n')
# 查询
def search(self,data):
# 判断是否为空
if self.is_empty():
print('空链表')
# 对比每一个数值是不是等于查询值
else:
cur = self.__head
while cur.next is not self.__head:
if cur.data == data:
return True
# 指针跳转
cur = cur.next
# 由于在判断最后一个结点的值之前会退出循环,
# 需要单独判断一下最后一个值等不等于data
if cur.data == data:
return True
return False
# 头部增加
# 尾部结点指针域next指向头部head,
# 头部增加之后就不可以指向原来头部head,
# 需要指向新的结点node,
# 令self.__head指向新结点node,
# 令尾部结点next指针域也指向新结点
# (尾部结点next指针域重新赋值(指向)新结点node)
# 实例化一个指针cur,
# 当cur.next=self.__head时即可,
# 此时修改属性:self.__head,
# node.next,
# 尾部结点next属性值(它需要指向新结点node),
# 先找到最后尾部结点,令尾部next=新结点node,
# 然后修改self.__head的值,
# 再令node.next=self.__head
def add(self,data):
# 1 实例化结点
node = Node(data)
# 2 找到尾部并判断空值
if self.is_empty():
self.__head = node
# 如果为空链表,此时添加则令结点next等于头部
node.next = self.__head
else:
# 找到尾部结点,此时尾部结点next=self.__head
# 实例化指针
cur = self.__head
while cur.next is not self.__head:
cur = cur.next
# 找到之后,退出循环,进行属性修改
# 先指针cur.next等于head,
# 尾部结点next等于新结点node,
# head等于新结点node,
cur.next = node
node.next = self.__head
self.__head = node
# 尾部增加
# 令最后一个值的next不能再指向头部head,
# 令尾部结点next指向新结点node,
# 新结点的next指针域应该指向头部head
# 当指针cur移动到最后
# (即找到并发现该结点next指向头部head),
# 如果是空链表,直接头部增加
def append(self,data):
# 实例化结点
node = Node(data)
# 判断空值
if self.is_empty():
self.__head = node
node.next = self.__head
# 寻找尾部结点
else:
# 指针寻找到next属性指向头部head的结点,
# 就找到了尾部的结点
cur = self.__head
# 修改属性
while cur.next is not self.__head:
cur = cur.next
# cur.next指向新结点node,
# 新结点node的next指针域指向self.__head
cur.next = node
node.next = self.__head
# 插入
# 需要指针cur找到相应位置,在对相应位置进行修改
# 新结点node的next指向原来的结点,
# 前一位置的结点的next指向新结点node,
# 不仅要找到相应位置的结点,
# 还要找到相应结点的前一位置进行修改next属性,
# 令新结点node等于cur当前的结点
# (即等于cur,因为此时cur=当前结点),
# 如果插入的位置长于链表长度,则为尾部添加
def insert(self,data,pos):
# 判断空值,如果是空,则头部增加
if pos <= 0:
self.add(data)
# 如果非空,如果位置大于链表长度,则尾部增加
elif pos > self.length():
self.append(data)
else:
# 中间位置增加,先用cur指针找到指定位置的前一位置(pos-1的位置)
# 找到之后,先令新结点node.next等于cur.next,
# 同时改cur.next指向新结点node,
# 如果顺序调转,则无法找到后面的链表
node = Node(data)
cur = self.__head
count = 0
# 利用计数器count找到pos-1
# (目标修改结点的前一个值)的位置
while count < (pos -1):
cur = cur.next
count += 1
# 属性修改
node.next = cur.next
cur.next = node
if __name__ == '__main__':
link = Singlecyclink()
print(link.is_empty())
link.add(1)
link.add(2)
link.add(3)
link.add(4)
link.append(5)
link.insert(7,3)
print(link.is_empty())
print(link.length())
link.travel()
# print(link.search(8))