#!/usr/bin/env python3
# -*- encoding:utf-8 -*-
"""
@author: jjcoder
@file: SingleCycleLinkList.py
@time: 9/11/197:31 AM
"""
class Node(object):
def __init__(self, item):
self.elem = item
self.next = None
class SingleCycleLinkList(object):
"""单向循环链表"""
def __init__(self, node=None):
self.__head = node
if node: # 这里要注意,如果初始化链表时.节点不为空,那么需要让节点的next区域指向自己
node.next = node
# 判断链表是否为空
def is_empty(self):
return self.__head is None
# 链表的长度
def length(self):
if self.is_empty(): # 如果链表为空,那么下面的循环判断将不适用,直接return 0;
return 0
cur = self.__head
count = 1 # 注意这里为什么选择1
while cur.next != self.__head: # 这里是循环的终止条件(只有一个节点的情况也是满足的)
count += 1
cur = cur.next
return count
# 遍历链表
def travel(self):
if self.is_empty(): # 当链表为空时直接返回
return
cur = self.__head # 对于单个节点的时候也是满足条件的
while cur.next != self.__head:
print(cur.elem, end=" ")
cur = cur.next
# 退出循环,cur指向尾节点,但是却未打印尾节点,这是需要打印一下尾节点
print(cur.elem, end=" ")
print()
# 在头部插入元素
def add(self, item):
node = Node(item)
if self.is_empty(): # 空链表的处理方式
self.__head = node
node.next = node
else:
# 先不在链表中插入节点,然后对链表遍历找到尾节点,然后记录下来(用于后面头插法使用)
# 另外一种方式是: 先在链表中插入一个节点,然后遍历新的链表
cur = self.__head
while cur.next != self.__head: # 单个节点这里也满足
cur = cur.next
# 退出循环,cur指向尾节点
node.next = self.__head
self.__head = node
cur.next = node # 这后面的写法比较灵活,自行选择
# 在尾部插入元素
def append(self, item):
node = Node(item)
if self.is_empty(): # 当链表为空时
self.__head = node
node.next = node
else:
cur = self.__head # 对于只有一个节点的情况也满足
while cur.next != self.__head:
cur = cur.next
node.next = self.__head
cur.next = node
# 在任意位置插入元素
def insert(self, pos, item):
# 这里的pos是从0开始的
node = Node(item)
# 如果pos<=0理解为在头部插入元素,不支持反向插入
if pos <= 0:
self.add(item)
# 如果pos>length() - 1, 就理解为在尾部插入元素,但是这里需要注意如果pos=length - 1,并不是在尾部插入元素,
# 而是在最后面元素的前一位插入.
elif pos > (self.length() - 1):
self.append(item)
else:
cur = self.__head
# for i in range(pos - 1): # 这种方式也是可以的
count = 0
while count < (pos - 1):
# 为防止后面的节点被丢弃,先将新节点的next区域指向cur的next区域,然后在将cur的next指向新节点
# 这里也可以定义一个pre游标,为了方便继续使用cur游标
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
# 查找元素
def search(self, item):
if self.is_empty(): # 判断链表为空时
return False
cur = self.__head
while cur.next != self.__head:
if cur.elem == item:
return True
else:
cur = cur.next
# 这里会出现最后一个节点没有被判断(cur指向尾节点), 所以这里需要特殊判断
if cur.elem == item:
return True
return False
# 删除元素
def remove(self, item):
if self.is_empty(): # 判断链表为空
return
cur = self.__head
pre = None
# 如果是空链表也是满足条件的
while cur.next != self.__head:
if cur.elem == item:
# 如果删除的元素恰好是首节点
# 如果链表只有一个节点,下面的操作也满足
# 先判断此节点是否是头节点
if cur == self.__head:
# 头节点插入元素
# 找到为节点
rear = self.__head
while rear.next != self.__head:
rear = rear.next
self.__head = cur.next
rear.next = self.__head
else:
# 如果删除的节点是尾节点,下面也是可以不满足条件的(因为尾节点并没有进入循环)
# 中间节点插入元素
pre.next = cur.next
return # 这里把break改成return就可以了
else:
# 下面这两行代码顺序不能变
pre = cur
cur = cur.next
# 退出循环,cur指向尾节点
if cur.elem == item:
if cur == self.__head: # 链表只有一个节点
self.__head = None
else:
pre.next = cur.next # 这里出现过问题,需要着重注意
if __name__ == "__main__":
single_obj = SingleCycleLinkList()