这一部分虽然大部分原理与单向链表相似。但是比单向链表多分析“头节点、只有一个节点、中间节点、尾部节点”,针对较为复杂的操作,进行了详细的分析。其余简单的部分可以参考“单向链表”。
单向循环链表
单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
单向循环链表的操作
节点定义
链表中最后一个节点的next域不再为None,而是指向链表的头节点。因此它的节点定义与 “单向链表与双向链表明显不同”
// An highlighted block
class SingleLinkList(object):
"""单链表的结点"""
def __init__(self,item=None,node=None):
self.item = item
self.next = None
self._head = node
if node:
node.next=node
计算链表长度
判断cur的下一个节点是否是头结点
// An highlighted block
"""链表长度"""
def length(self):
if self.is_empty():
return 0
cur = self._head # cur初始时指向头节点
count = 1
while cur.next != self._head: #判断cur的下一个节点是否为头结点
count=count+1
cur=cur.next # 将cur后移一个节点
return count
遍历链表元素
判断cur的下一个节点是否是头结点
// An highlighted block
"""遍历链表"""
def travel(self):
#判断是否为空链表
if self.is_empty():
return
cur = self._head
while cur.next != self._head:
print(cur.item,end="\t")
cur = cur.next
#退出循环时,cur指向末尾节点,但是节点鹅元素未被打印
print(cur.item)
在头部添加元素
首先使用cur遍历所有元素,找到尾节点,再将尾节点next域指向新添加的元素
// An highlighted block
"""头部添加元素"""
def add(self, item):
node = Single_CircleLinkList(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=self._head
node = Single_CircleLinkList(item)
node.next = self._head
self._head = node
在尾部添加元素
首先使用cur遍历所有元素,找到尾节点,再将尾节点next域指向新添加的元素,新元素的next域指向头结点
// An highlighted block
"""尾部添加元素"""
def append(self, item):
node = Single_CircleLinkList(item)
if self.is_empty(): # 先判断链表是否为空,若是空链表,则将_head指向新节点
self._head = node # 若不为空,则找到尾部,将尾节点的next指向新节点
node.next=node
else:
cur = self._head
while cur.next!= self._head: # 判断下一个节点是否为None
cur = cur.next
node.next=self._head
cur.next = node
删除元素
这一部分原理跟单链表相似,但是在具体分析中,掺杂了空链表、第一个元素、只有一个节点的删除、中间元素的删除和尾部元素的删除,因此单独拿出来分析。其余的在“单向循环链表”中提到的,由于分析较为简单,没有单独分析。
"""删除一个节点"""
#单独说明 引入尾部节点 rear,尾结点是指链表中最后一个节点,在单链表中,尾结点的指针一般为空,即没有保存其他节点的存储位置信息。但在双向链表中,尾结点一般指向链表中第一个节点。
#引入rear的原因是 通过rear游标找到最后一个节点
def remove(self, item):
# 若链表为空,则直接返回
if self.is_empty():
return
cur = self._head
pre = None
while cur.next != self._head:
if cur.item == item:
# 先判断此节点是否为头结点
if cur == self._head:
#头结点的情况
#先找尾节点,然后由尾节点找到指向的头节点
rear = self._head
rear = rear.next
while rear.next!=self._head:
rear = rear.next
self._head = cur.next
rear.next=self._head
else:
#中间节点
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
#退出循环,cur指向尾节点
if cur.item==item:
if cur==self._head:
#链表只有一个节点
self._head=None
else:
pre.next=cur.next
var foo = 'bar';
修改元素
找到指定位置的元素,然后用指定的值去修改
// An highlighted block
def change(self, pos,num,item=None):
self.item = item
# node = SingleLinkList(item)
cur = self._head
count = 0
# 通过计数判断是否移动到指定位置的前一个位置
while count < (pos - 1):
count += 1
cur = cur.next
cur.item =num
元素反转
// An highlighted block
class Node(object):
def __init__(self, item=None, next=None):
self.item = item
self.next = next
def rev(link):
pre = link
cur = link.next
pre.next = None
while cur:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
return pre
if __name__ == '__main__':
link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
root=link
while root:
print(root.item,end="\t")
root = root.next
print(end="\n")
root = link.rev()
while root:
print(root.item,end="\t")
root = root.next
程序运行
// An highlighted block
"""单链表的结点"""
class SingleLinkList(object):
def __init__(self,item=None,node=None):
self.item = item
self.next = None
self._head = node
if node:
node.next=node
'''判断链表是否为空'''
def is_empty(self):
return self._head == None
"""链表长度"""
def length(self):
cur = self._head # cur初始时指向头节点
count = 0
while cur != None: # 尾节点指向None,当未到达尾部时
count=count+1
cur=cur.next # 将cur后移一个节点
return count
"""遍历链表"""
def travel(self):
cur = self._head
while cur != None:
print(cur.item,end="\t")
cur = cur.next
print(end="\n")
"""尾部添加元素"""
def append(self, item):
node = SingleLinkList(item)
if self.is_empty(): # 先判断链表是否为空,若是空链表,则将_head指向新节点
self._head = node # 若不为空,则找到尾部,将尾节点的next指向新节点
else:
cur = self._head
while cur.next!= None: # 判断下一个节点是否为None
cur = cur.next
cur.next = node
"""头部添加元素"""
def add(self, item):
node = SingleLinkList(item)
node.next = self._head
self._head = node
"""在指定位置添加元素
添加的元素是 (2,50),则pos=2
"""
def insert(self, pos, item):
# 判断指定位置是进行头部添加还是尾部添加
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
node = SingleLinkList(item)
cur = self._head
count = 0
# 通过计数判断是否移动到指定位置的前一个位置
while count < (pos - 1):
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
"""查找节点是否存在"""
def search(self, item):
cur = self._head
while cur != None:
if cur.item == item:
print("True")
return True
else:
cur = cur.next
print("False")
return False
"""删除一个节点"""
def remove(self, item):
# 若链表为空,则直接返回
cur = self._head
pre = None
# 若头节点的元素就是要查找的元素item
while cur != None:
if cur.item == item:
# 先判断此节点是否为头结点
if cur == self._head:
self._head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
"""在指定位置添加元素
添加的元素是 (2,50),则pos=2
"""
def insert(self, pos, item):
# 判断指定位置是进行头部添加还是尾部添加
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
node = SingleLinkList(item)
cur = self._head
count = 0
# 通过计数判断是否移动到指定位置的前一个位置
while count < (pos - 1):
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
'''修改元素'''
def change(self, pos,num,item=None):
self.item = item
# node = SingleLinkList(item)
cur = self._head
count = 0
# 通过计数判断是否移动到指定位置的前一个位置
while count < (pos - 1):
count += 1
cur = cur.next
cur.item =num
if __name__=="__main__":
a=SingleLinkList()
print(a.is_empty())
print(a.length())
#在尾部增加元素
a.append(1)
print(a.is_empty())
print(a.length())
a.append(2)
a.append(3)
a.append(4)
a.append(5)
a.append(6)
a.travel()
#在头部增加元素
a.add(20000)
a.travel()
# # 在指定位置插入
a.insert(3,50)
a.travel()
print(a.length())
# #删除元素
a.remove(20000)
a.travel()
# #查找元素
a.search(50)
a.search(10000)
a.search(30000)
a.insert(3,80)
a.travel()
a.change(3,100)
a.travel()