Python实现单向循环链表

关于链表的介绍,请参考:https://blog.csdn.net/weixin_43790276/article/details/104033254

本篇文章使用 Python 来实现一个单向循环链表。

一、定义一个创建节点的类

链表是由一个个的节点组成的,在创建链表之前,要先创建节点,然后把节点“串”到链表上。在同一个链表中,每个节点的结构都相同,只是节点中保存的数据不同和引用不同,所以提前声明一个创建节点的类,需要创建节点时实例化即可。

# coding=utf-8
class Node(object):def __init__(self, data):self.data = dataself.next = None

单向循环链表的节点包含两个域,一个信息域(元素域)和一个链接域(引用域)。在实例化一个节点时,传入数据保存到信息域中,链接域默认为空,当对节点进行“链接”操作时,再设置具体的链接域。

单向循环链表中,尾节点的链接域指向头节点。

二、定义一个单向循环链表类

实例化一个单向循环链表时,这个链表是一个空链表,把节点依次“链接”上去后,链表中才有节点和数据。

在链表中,要找到链表的某个节点,需要从链表的头节点开始,依次寻找,所以在实例化单向循环链表时,必须定义好链表的“头”,当加入头节点时,将链表的“头”指向头节点。

定义一个单向循环链表类 SingleCycleLinkList,初始化一个单向循环链表时,链表的“头”指向空值,默认为空链表。

class SingleCycleLinkList(object):def __init__(self):self.__head = None

三、实现单向循环链表的展示功能

    def is_empty(self):return not self.__headdef show(self):if self.is_empty():print('空链表')returncur = self.__headwhile cur.next != self.__head:print(cur.data, end=' → ')cur = cur.nextprint(cur.data, '→ ')

先实现判断链表是否为空的方法 is_empty() ,实例化单向循环链表时,默认是空的,链表的头指向为空。所以,如果链表的头指向为空(对应布尔值False), is_empty() 的值就为 True ,反之。

展示链表中的数据,就是将链表中所有的数据依次打印输出。链表不像顺序表有“索引”,链表只能从头节点开始依次往下找,直到尾节点。所以链表不能使用 for 循环进行遍历,只能使用 while 循环进行遍历,并使用一个游标 cur 来记录当前所处的节点,通过游标 cur 向下一个节点移动来遍历,当链接域指向头节点时(尾节点)停止。

这里要注意单向循环链表与单向链表的区别,遍历时单向链表的尾节点是指向空,单向循环链表的尾节点是指向头节点,不仅要修改判断的条件,还要注意尾节点是否已经进行了逻辑处理,不能漏了。

实现 show() 方法时,为了更形象地展示链表中每个节点的关系,我在每个节点之后使用右箭头连接(空链表无效果)。

if __name__ == '__main__':s = SingleCycleLinkList()print("is_empty: ", s.is_empty())s.show()

运行结果:

is_empty:  True
空链表

四、实现单向循环链表中添加数据的功能

    def add(self, data):node = Node(data)if self.is_empty():self.__head = nodenode.next = self.__headreturncur = self.__headwhile cur.next != self.__head:cur = cur.nextcur.next = nodenode.next = self.__headself.__head = nodedef append(self, data):if self.is_empty():self.add(data)returncur = self.__headwhile cur.next != self.__head:cur = cur.nextnode = Node(data)cur.next = nodenode.next = self.__headdef length(self):if self.is_empty():return 0length = 1cur = self.__headwhile cur.next != self.__head:length += 1cur = cur.nextreturn lengthdef insert(self, index, data):if index <= 0:self.add(data)returnif index > self.length() - 1:self.append(data)returncur = self.__headfor i in range(index-1):cur = cur.nextnode = Node(data)node.next = cur.nextcur.next = node

添加数据到单向循环链表中,无论将数据添加到链表的哪个位置,都要先创建一个新节点,新节点里存放对应的数据,然后将新节点添加到指定的位置。

add(data):从头部添加时,链表原来的头节点会成为第二个节点,新节点成为头节点。添加分为三步,第一步将新节点的链接域指向原来的头节点,第二步将尾节点指向新节点,第三步将链表的头指向新节点。在第二步中,要先找到尾节点,使用一个游标从头节点开始,依次找到尾节点。如果原来的链表为空,将链表的头指向新节点,再将新节点的链接域指向头,即使只有一个节点也要保证循环的结构。

append(data):从尾部添加时,找到链表的尾节点,先将尾节点的链接域指向新节点,再将新节点的链接域指向头节点。如果原来的链表为空,则与从头部添加一样,直接调用即可。

insert(index, data):在指定位置添加数据时,要使用一个游标 cur 来找到此位置的前一个节点,将新节点的链接域指向指定位置原来的节点,然后将游标记录的节点(指定位置的前一个节点)的链接域指向新节点,这样就成功将新节点插入到了指定位置。

如果指定的位置是负数或超过了链表最大长度,则需要特殊处理,上面的处理是负数在头部添加,超过最大长度在尾部添加。也可以直接抛出 IndexError ,这个自己按需选择。

同时,上面实现了获取链表长度的方法 length(),返回链表当前的节点个数。

    s.add(1)s.add(10)s.append(2)s.append(3)s.append(4)s.show()s.insert(1, 20)s.show()print("链表长度:", s.length())

运行结果:

10 → 1 → 2 → 3 → 4 →
10 → 20 → 1 → 2 → 3 → 4 →
链表长度: 6

五、实现单向循环链表的查询和修改功能

    def is_exist(self, value):if self.is_empty():return Falsecur = self.__headwhile cur.next != self.__head:if cur.data == value:return Truecur = cur.nextif cur.data == value:return Truereturn Falsedef index(self, value):if self.is_empty():return -1index = 0cur = self.__headwhile cur.next != self.__head:if cur.data == value:return indexcur = cur.nextindex += 1if cur.data == value:return indexreturn -1def setitem(self, index, value):if index < 0:raise IndexErrorif index > self.length() - 1:raise IndexErrorcur = self.__headfor i in range(index):cur = cur.nextcur.data = value

is_exist(value):判断一个数据是否存在链表中,遍历链表的每个节点,如果节点的数据值与目标值相等,则说明链表中存在目标值。

index(value):返回一个数据在链表中的第几个节点,与判断是否存在的实现方式一样,这里返回的是数据处于第几个节点中,如果链表中不存在这个数据,则返回-1。

setitem(index, value):修改指定位置的节点的数据,先根据给定的值,找到链表中该位置的节点,然后修改节点中的数据。如果指定位置小于零或大于链表长度,抛出 IndexError 。

    print(s.is_exist(100))print(s.index(20))s.setitem(2, 30)s.show()

运行结果:

False
1
10 → 20 → 30 → 2 → 3 → 4 → 

六、实现单向循环链表的删除功能

    def remove(self, index):if index < 0:raise IndexErrorif index > self.length() - 1:raise IndexErrorcur = self.__headprev = Nonefor i in range(index):prev = curcur = cur.nextif cur == self.__head:prev = self.__headwhile prev.next != self.__head:prev = prev.nextif prev == self.__head:self.__head = Nonereturnprev.next = self.__head.nextself.__head = self.__head.nextreturnprev.next = cur.nextdef delete(self, value):cur = self.__headprev = Nonewhile cur.next != self.__head:if cur.data == value:if cur == self.__head:prev = self.__headwhile prev.next != self.__head:prev = prev.nextprev.next = cur.nextself.__head = cur.nextreturnprev.next = cur.nextreturnprev = curcur = cur.nextif cur.data == value:if cur == self.__head:self.__head = Nonereturnprev.next = cur.nextreturndef delete_all(self, value):cur = self.__headprev = Nonewhile cur.next != self.__head:if cur.data == value:if cur == self.__head:prev = self.__headwhile prev.next != self.__head:prev = prev.nextprev.next = cur.nextself.__head = cur.nextself.delete_all(value)returnprev.next = cur.nextself.delete_all(value)returnprev = curcur = cur.nextif cur.data == value:if cur == self.__head:self.__head = Nonereturnprev.next = cur.nextself.delete_all(value)return

remove(index):删除指定位置的节点,使用游标 cur 找到节点,使用另一个游标 prev 来记录当前节点的前一个节点,将该位置的前一个节点的链接域指向该位置的后一个节点。如果删除的是头节点,先找到链表的尾节点,然后将尾节点指向第二个节点,再将头指向第二个节点。如果链表只有一个节点,删除时将链表的头指向空即可。如果指定的位置小于零或超过链表长度,则抛出 IndexError 。

delete(value):删除指定值的节点,先遍历链表,找到对应值的节点,删除的方式与 remove(index) 相同。使用这个方法,如果链表中有多个满足条件的节点,只会删除最前面的一个节点。

delete_all(value):删除数据等于指定值的所有节点,如果链表中有多个节点的数据与目标值相等,删除第一个节点后,链表的长度发生了改变,继续遍历和删除节点,会出现删除不完全甚至程序出错的情况。所以在删除第一个节点之后,递归调用自身,这样重新遍历时使用的是新的链表长度,不会出现漏删或错误。

    s.remove(3)s.show()s.delete(4)s.show()s.add(4)s.insert(3, 4)s.insert(3, 4)s.append(4)s.append(4)s.show()s.delete_all(4)s.show()

运行结果:

10 → 20 → 30 → 3 → 4 →
10 → 20 → 30 → 3 →
4 → 10 → 20 → 4 → 4 → 30 → 3 → 4 → 4 →
10 → 20 → 30 → 3 → 

以上就是用 Python 实现的单向循环链表及单向循环链表的一些简单操作方法。

Python实现单向循环链表相关推荐

  1. node 获取表单数据 为空_数据结构与算法(python)单向循环链表

    单向循环链表 单链表的一个变形是单向循环链表, 链表的最后一个节点的next域不再为None, 而是指向链表的头节点. 单向循环链表如图所示: 单向循环链表 同样单向循环链表也是要使用python来对 ...

  2. python之链表、单链表、双向链表、单向循环链表

    python之链表.单链表.双向链表.单向循环链表 链表 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时,又需要进行数据的搬迁,所以使用起来并非很灵活 链表结构可以充分利用计算机 ...

  3. 算法—详细讲解单向循环链表的实现(python)

    单向循环列表如图所示 单向循环链表的实现 一.往链表头部添加一个节点值为4 1.新增一个节点node=Node(4) 新建一个节点 node=Node(data)if self.is_empty(): ...

  4. python约瑟夫环单向循环链表_约瑟夫环的单向循环链表的实现代码

    /************************************************************************* > File Name: JosephCir ...

  5. 单向循环链表的增、删、查、改、python实现,超详细讲解

    单向循环链表的增.删.查.改 具体代码如下: class Node(object):"""链表单节点实现"""def __init__(se ...

  6. python单向循环链表_python实现单向循环链表 -- 详细思路分析

    单向循环链表其实就是在单向链表的基础上,让尾节点的下一个节点指向头节点,整个链表形成一个闭环.所以在整体思路上,和单向链表类似,只是在考虑问题时,需要考虑尾部节点指向头部节点的指针. 1.构造单向循环 ...

  7. python单向循环链表

    入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删. 目录 一.单向循环链表 二.建立节点对象 三.链表对象的初始定义 四.判断链表是否为空 五.获 ...

  8. 链表——单链表、单向循环链表、双向链表

    目录 1 单链表 节点实现 单链表操作 单链表实现 测试 链表与顺序表对比 2 单向循环链表 操作 实现 测试 3 双向链表 操作 实现 测试 1 单链表 单向链表也叫单链表,是链表中最简单的一种形式 ...

  9. 线性表—单向循环链表

    开始没看单向循环链表,感觉应该很简单,但实际上有几个概念不是很清楚: 头结点,头指针,尾指针,尾节点??? [个人理解]:头结点就是一个链表中实际存储数据的那个节点的前一个节点,这个节点不存储数据,只 ...

最新文章

  1. awk4.0 — awk格式化
  2. PHP函数,方法,接口
  3. ubuntu16.04 内核源码编译
  4. python ssd目标检测_目标检测算法之SSD的数据增强策略
  5. 计算机科学中最重要的 32 个算法
  6. CSS面试题汇总(三)
  7. 进化算法求解TSP问题
  8. 移动硬盘或U盘无法安全弹出怎么快速安全弹出?
  9. C语言画圣诞树源码(树界降临)
  10. 【动态规划】爬楼梯爬的不仅仅是楼梯
  11. 黄芪桂圆枸杞红枣茶的作用
  12. GOOGLE地图基站定位-Google Mobile Maps API
  13. 时至今日,写字依然是很好的职场“捷径”
  14. 多大样本量才能模拟出中心极限定理
  15. MySQL数据库常用基本语句及管理
  16. 查询表历史某刻的表数据
  17. 跪了!3秒钟完成别人半天的工作量!网友:别再用Excel了!
  18. 实验三 可综合时序逻辑电路实验
  19. 论文阅读04:使用序列标注的方式解决实体和关系的联合抽取
  20. Android高仿抖音照片电影功能

热门文章

  1. 解决df -h卡死问题
  2. 暑假周总结二7.22
  3. tomcat7下配置session复制和nginx做负载均衡
  4. 实实在在做一位教书匠(来自网络)
  5. 我要成为一名优秀的程序员!
  6. Mongodb 与sql 语句对照
  7. Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 10.x
  8. 分布式数据库中间件 MyCat 安装及使用
  9. Kubernetes入门指南
  10. Linux crontab下关于使用date命令和sudo命令的坑