Python全栈(二)数据结构和算法之4.单向循环链表的实现
2020-01-11 13:26
417 查看
文章目录
一、单项循环链表长度&判空实现
1.循环链表定义
是一种特殊的单链表,唯一的区别是:
单链表的尾结点指针指向空地址,表示这就是最后的结点了;
循环链表的尾结点指针是指向链表的头结点。
2.is_empty()
与单链表一致。
def is_empty(self): '''判断是否为空''' return self.__head == None
3.length()
cur.next = self.__head时循环结束,且因最后一次循环不会执行,所以count不会加1,所以count要哦才能够1开始计数。
并且为空时,直接返回0。
def length(self): '''链表长度''' #判断是否为空链表 if self.is_empty(): return 0 # cur即游标,指向首节点,用来遍历 cur = self.__head count = 1 # 当未到达尾部时 while cur.next != self.__head: count += 1 # 将游标向后移动一位 cur = cur.next return count
二、单项循环链表遍历、头插法&尾插法
1.遍历travel()
cur.next = self.__head时循环结束。
空链表时直接返回。
def travel(self): '''遍历链表''' #链表为空时 if self.is_empty(): return cur = self.__head while cur.next != self.__head: print(cur.item, end=' ') cur = cur.next #退出循环时,cur指向尾节点,单独打印 print(cur.item)
2.头部添加add():
将新节点指向head的下一个节点,head指向新节点,尾节点指向新节点,第三步顺序可以在第一或第二步。
为空链表时,__head指向新节点,新节点指向自己(即__head)。
def add(self, item): '''链表尾部添加元素''' # 创建一个保存数据的节点 node = Node(item) # 判断链表是否为空,若为空,则将__head指向新节点,新节点指向头部 if self.is_empty(): self.__head = node node.next = self.__head #等价于node.next = node #若不为空 else: cur = self.__head #找到尾部 while cur.next != self.__head: cur = cur.next #新节点指向__head node.next = self.__head #__head指向新节点 self.__head = node # 将尾节点指向新节点,此句可以在self.__head = node或node.next = self.__head之前 cur.next = node
3.append()尾部添加
找到尾节点:
尾节点指向新节点,新节点指向头部。
也要判断是否为空链表。
def append(self, item): '''链表尾部添加元素''' # 创建一个保存数据的节点 node = Node(item) #判断是否为空链表 if self.is_empty(): self.__head = node node.next = self.__head # 等价于node.next = node else: cur = self.__head # 找到尾节点 while cur.next != self.__head: cur = cur.next # 尾节点指向新节点 cur.next = node #新节点指向__head node.next = self.__head
三、单项循环链表删除&搜索
1.insert()
新节点指向目标位置,目标位置前一个位置指向新节点。
def insert(self, pos, item): '''指定位置添加元素''' # 若指定位置为第一个位置之前,则执行头部插入 if pos <= 0: self.add(item) # 若指定位置超过链表尾部,则执行尾部插入 elif pos > self.length() - 1: self.append(item) # 找到指定位置 else: node = Node(item) cur = self.__head count = 0 while count < pos - 1: count += 1 cur = cur.next # 将新节点node的next指向插入位置的节点 node.next = cur.next # 将插入位置的前一个节点的next指向新节点 cur.next = node
2.search()
如果为空,直接返回False。
并且在循环后判断尾节点是否符合。
def search(self, item): '''查找节点是否存在''' if self.is_empty(): return False cur = self.__head while cur.next != self.__head: # 判断第一个节点 if cur.item == item: return True # 未找到,继续向后移动 else: cur = cur.next #循环退出,cur指向尾节点 if cur.item == item: return True return False
3.remove()
如果删除的节点为头节点:
如果不止头节点一个节点,__head指向当前的下一个节点;
如果只有head一个节点,则__head指向None。
如果删除的节点不是头节点:
pre.next = cur.next,并且需要循环,同时要对尾节点进行判断。
def remove(self, item): '''删除节点''' #如果链表为空,直接返回 if self.is_empty(): return cur = self.__head pre = None #头节点的元素就是要删除的元素 if cur.item == item: #链表中的节点不止一个 if cur.next != self.__head: while cur.next != self.__head: cur = cur.next #循环结束,cur指向尾节点 cur.next = self.__head.next self.__head = cur.next #只有一个节点 else: self.__head = None #头节点不是要删除的元素 else: while cur.next != self.__head: if cur.item == item: #删除 pre.next = cur.next return #继续往后遍历 else: pre = cur cur = cur.next #要删除的节点是最后一个元素时 if cur.item == item: pre.next = cur.next #pre.next = self.__head也可
整个单项循环链表的实现如下:
class Node(object): '''节点''' def __init__(self,item): '''初始化''' self.item = item #next是下一个节点的标识 self.next = None class SinCycLinkList(object): '''循环链表''' def __init__(self,node = None): self.__head = None if node: node.next = node def is_empty(self): '''判断是否为空''' return self.__head == None def length(self): '''链表长度''' #判断是否为空链表 if self.is_empty(): return 0 # cur即游标,指向首节点,用来遍历 cur = self.__head count = 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.item, end=' ') cur = cur.next #退出循环时,cur指向尾节点,单独打印 print(cur.item) def add(self, item): '''链表头部添加元素''' # 创建一个保存数据的节点 node = Node(item) # 判断链表是否为空,若为空,则将__head指向新节点,新节点指向头部 if self.is_empty(): self.__head = node node.next = self.__head #等价于node.next = node #若不为空 else: cur = self.__head #找到尾部 while cur.next != self.__head: cur = cur.next #新节点指向__head node.next = self.__head #__head指向新节点 self.__head = node # 将尾节点指向新节点,此句可以在self.__head = node或node.next = self.__head之前 cur.next = node def append(self, item): '''链表尾部添加元素''' # 创建一个保存数据的节点 node = Node(item) #判断是否为空链表 if self.is_empty(): self.__head = node node.next = self.__head # 等价于node.next = node else: cur = self.__head # 找到尾节点 while cur.next != self.__head: cur = cur.next # 尾节点指向新节点 cur.next = node #新节点指向__head node.next = self.__head def insert(self, pos, item): '''指定位置添加元素''' # 若指定位置为第一个位置之前,则指向头部插入 if pos <= 0: self.add(item) # 若指定位置超过链表尾部,则执行尾部插入 elif pos > self.length() - 1: self.append(item) # 找到指定位置 else: node = Node(item) cur = self.__head count = 0 while count < pos - 1: count += 1 cur = cur.next # 将新节点node的next指向插入位置的节点 node.next = cur.next # 将插入位置的前一个节点的next指向新节点 cur.next = node def remove(self, item): '''删除节点''' #如果链表为空,直接返回 if self.is_empty(): return cur = self.__head pre = None #头节点的元素就是要删除的元素 if cur.item == item: #链表中的节点不止一个 if cur.next != self.__head: while cur.next != self.__head: cur = cur.next #循环结束,cur指向尾节点 cur.next = self.__head.next self.__head = cur.next #只有一个节点 else: self.__head = None #头节点不是要删除的元素 else: while cur.next != self.__head: if cur.item == item: #删除 pre.next = cur.next return #继续往后遍历 else: pre = cur cur = cur.next #要删除的节点是最后一个元素时 if cur.item == item: pre.next = cur.next #pre.next = self.__head也可 def search(self, item): '''查找节点是否存在''' if self.is_empty(): return False cur = self.__head while cur.next != self.__head: # 判断第一个节点 if cur.item == item: return True # 未找到,继续向后移动 else: cur = cur.next #循环退出,cur指向尾节点 if cur.item == item: return True return False s = SinCycLinkList() print(s.is_empty()) print(s.length()) s.add(1) s.add(2) s.add(3) s.add(4) s.travel() s.append(5) s.append(6) s.insert(-1,7) s.insert(12,8) s.insert(5,9) s.travel() print(s.search(3)) print(s.search(10)) s.remove(6) s.travel()
对单项循环链表进行测试,结果如下:
True 0 4 3 2 1 7 4 3 2 1 9 5 6 8 True False 7 4 3 2 1 9 5 8
小结:
单项循环链表的实现要结合单链表,要对它们的相同和不同之处进行比较。
很显然,单向循环链表实现的时候要考虑的情况比单链表更多,也更复杂,要在对比中学习,举一反三。
并且在每一个方法中
cur.next != self.__head这个循环判断条件都出现了,所以找到实现的边界条件极为重要。
同时,要考虑各种特殊情况,比如链表为空,只有一个节点,对尾节点的处理等情况。
大家也可以关注我的公众号:Python极客社区,在我的公众号里,经常会分享很多Python的文章,而且也分享了很多工具、学习资源等。另外回复“电子书”还可以获取十本我精心收集的Python电子书。
- 点赞 2
- 收藏
- 分享
- 文章举报
相关文章推荐
- python实现数据结构(三)——单向循环链表实现
- 用Python实现数据结构中的单向循环链表
- Python全栈(二)数据结构和算法之5.双向链表的实现和栈的实现
- PHP数据结构与算法:单向循环链表
- 数据结构(三)——单向循环链表的java实现
- Python实现数据结构,栈,队列(单向队列,双向队列,环形队列),链表
- 单向链表、单向循环链表、双向链表(Python实现)
- python单向循环链表原理与实现方法示例
- 数据结构与算法:单向链表实现与封装(有头)
- C++类模板 实现双向循环链表的基本算法 《数据结构》(C++版 北京科海)中摘抄
- Python实现基础数据结构--单向链表
- 用Python实现数据结构中的单向链表
- Python全栈(二)数据结构和算法之7.选择排序、插入排序和希尔排序的实现
- 用Python实现的数据结构与算法:链表
- Python实现的单向循环链表功能示例
- Python写数据结构:单向循环链表
- 算法与数据结构-单向链表的基本操作C语言实现
- 数据结构学习之链表(单向、单循环以及双向)(递归实现)
- 【数据结构】单向循环链表实现
- 数据结构 P36-37 算法实现 双向循环链表的插入与删除