单向循环链表

单链表的一个变形是单向循环链表, 链表的最后一个节点的next域不再为None, 而是指向链表的头节点.

单向循环链表如图所示:

单向循环链表

同样单向循环链表也是要使用python来对它的基本功能进行一个封装. 总体大致的功能如下:

  • is_empty() 判断链表是否为空
  • length() 返回链表的长度
  • travel() 遍历
  • add(item) 在头部添加一个节点
  • append(item) 在尾部添加一个节点
  • insert(pos, item) 在指定位置pos添加节点
  • remove(item) 删除一个节点
  • search(item) 查找节点是否存在

注意: 区别单链表的操作如图:(图为单链表操作)

单链表的操作

单向循环链表的操作多了一个尾部指向头部的链接.

python实现其基本功能

事先定义一个节点, 包含数据元素的本身和它 的next区域的指向None.

class Node(object):     '''节点    '''    def __init__(self, item):        self.item = item        self.next = None

结果如下(还是那句话, 写完一个功能调试一下):

node节点运行调试图

总体功能布局

同样需要事先初始化节点, 其实就是对之前的单链表的功能进行直接的更改, 可以直接把之前的代码复制过来,看看是否可以满足单向循环链表的的功能, 如果可以直接过去就好, 如果不行重新修改. (注意和之前单链表的区别, 循环的终止点, 设置循环的终止, 到哪里才算是一次循环的完成)

class SinCycLinkedlist(object):    '''    单向循环链表    '''    def __init__(self):        self.__head = None    def is_empty(self):        '''        判断链表是否为空        '''    def length(self):        '''        返回链表的长度        '''    def travel(self):        '''        遍历链表        '''    def add(self, item):        '''        头部添加节点        '''    def append(self, item):        '''        尾部添加节点        '''    def insert(self, pos, item):        '''        指定位置添加节点        '''    def remove(self, item):        '''        删除节点        '''    def search(self, item):        '''        查找节点是否存在        '''if __name__ == "__main__":    ll = SinCycLinkedlist()

基本功能大致如上.

判断链表是否为空

这功能和之前的单链表是一样的, 只需要判断头节点是否为空, 直接返回True or False就好了.

def is_empty(self):    '''    判断链表是否为空    '''    return self.__head == None

返回链表长度

通过循环遍历来计算元素的个数, 没遍历一个count就加1, 但是这里的循环的终止条件, 要变, 不能使用之前的. 终止条件改为 cur.next != self.__head 直接判断最后一个节点的下一个区域是否指向头结点, 如果是结束一次循环, 如果不是继续往后遍历.代码如下:

def length(self):    '''    返回链表的长度    '''    if self.is_empty():        return 0    count = 1    cur = self.__head    while cur.next != self.__head:        count += 1        cur = cur.next    return count

遍历链表打印里面的元素

同样是和之前的单链表的是一样的, 只是循环的条件得改掉, 由于是头尾相连的, 导致之前的cur != None 在非空链表中不可以使用每个元素都是有值的, 没有指向None的元素. 每个元素的next区域都有指向, 每个元素cur.next != None也是不可以使用的.所以还是改成cru.next != self.__head以最后一个节点和头节点作为比较.代码如下:

def travel(self):    '''    遍历链表    '''    if self.is_empty():        return    cur = self.__head    print (cur.item) # 头节点没有参与循环, 要直接打印出来    while cur.next != self.__head:        cur = cur.next        print (cur.item)    print ("") # 换行

头部添加节点

单向循环链表头部添加节点

先定义要添加的节点node, 判断是否为空, 如果是空的话, 直接按照头结点的添加, 头节点指向node, node的next区域指向头节点.如果不是, 添加的节点指向__head, 移到链表尾部, 将结尾部节点的next指向node. 如代码:

def add(self, item):    '''    头部添加节点    '''def travel(self):    '''    遍历链表    '''    if self.is_empty():        return    cur = self.__next    print (cur.item) # 头节点没有参与循环, 要直接打印出来    while cur.next != self.__head:        cur = cur.next        print (cur.item)    print ("") # 换行def travel(self):    '''    遍历链表    '''    if self.is_empty():        return    cur = self.__next    print (cur.item) # 头节点没有参与循环, 要直接打印出来    while cur.next != self.__head:        cur = cur.next        print (cur.item)    print ("") # 换行    node = Node(item)    if self.is_empty():        self.__head = node        node.next = self.__head    else:        # 添加的节点指向__head        node.next = self.__head        # 移到链表的尾部, 将尾部节点的next指向node        cur = self.__head        while cur.next != self.__head:            cur = cur.next        cur.next = node        # __head 指向添加node的        self.__head = node

链表尾部的添加

和之前的单链表差不多, 判断是否是空链表, 如果是头节点指向node, node的next区域指向self.__head, 如果不是, 移动到链表的尾部, 注意循环结束的条件cur.next != self.__head , 找到尾节点之后将尾节点指向node, 再将node指向头节点__head, 注意指向的先后顺序, 先是cur.next指向再是node的next指向, 注意区分先后顺序, 每种指向的区别, 先后的影响. 代码如下:

def append(self, item):    '''    尾部添加节点    '''    node = Node(item)    if self.is_empty():        self.__head = node        node.next = self.__head    else:        # 移动到链表的尾部        cur = self.__head        while cur.next != self.__head:            cur = cur.next        # 将尾节点指向node        cur.next = node        # 将node的指向头结点__head        node.next = self.__head

区别单链表的尾部添加节点, 区别注意尾部的指向问题. 单链表尾部如图所示:

单链表尾部添加, 注意区别

指定位置添加节点

基本思路和前面的单链表一样.先判断插入的位置. 如果是头部插入直接调用self.add()函数就可以 ( 这里使用pos<=0来表示头部的插入, 传递进来的参数小于0了, 就认为他是要在头部进行插入 ) , 如果是尾部直接调用前面的self.append()函数就好 ( 使用pos > self.length - 1 来表示在尾部插入传递进来的参数, 要求的位置超过了链表应有的长度, 就认为直接在尾部进行插入 ) . 注意pos参数传递过来, 判断插入的位置的时候注意一定要区别和链表本身的长度之间的区别, 是加一还是减一. 指定其他位置的插入, 使用count来计数, 如果count < pos - 1 接着向后移动就可以了 , 如果不满足条件了, 注意节点插入的先后顺序. 思考为什么是count < pos - 1 而不是正好等于或者加一. 详细代码如下:

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 = cur.next        cur.next = node

注意node的插入的先后顺序

删除一个节点

这里需要引入pre游标来辅助我们判断节点, 对节点进行删除.

判断链表是否为空, 如果是直接返回, 空链表不需要删除. 如果头结点的元素就是要查找的元素item, 进入分支判断, 如果链表不止一个节点, 先找到尾节点, 将尾节点的next指向第二个节点(注意这些节点之间next区域移动的先后顺序, 注意之间的区别). 如果链表只有一个节点该怎么办.

第一个节点不是要删除的, 先找到要删除的元素, 再通过区域的指向来进行删除. 代码如下:

def remove(self, item):    '''    删除节点    '''    # 若链表为空    if self.is_empty():        return    # 将cur 指向头节点    cur = self.__head    pre = None    # 若头节点就是要找的    if cur.item == item:        # 如果链表不止一个节点        if cur.next != self.__head:            # 先找到尾节点, 将尾节点的next指向第二个节点            while cur.next != self.__head:                cur = cur.next            # cur指向了尾节点            cur.next = self.__head.next            self.__head = self.__head.next        else:            # 链表只有一个节点            self.__head = None    else:        pre = self.__head        # 第一个节点不是要删除的        while cur.next != self.__head:            # 找到了要删除的元素            if cur.item == item:                # 删除                pre.next = cur.next                return            else:                pre = cur                cur = cur.next            # cur指向尾节点            if cur.item == item:                # 尾部删除                pre.next = cur.next

查找节点是否存在

这个功能和单链表中的差不多就是一个循环判断的条件不一样, 注意新的判断条件是cur的next区域是否等于头节点.详细代码如下:

def search(self, item):    '''    查找节点是否存在    '''    if self.is_empty():        return False    cur = self.__head    if cur.item == item:        return True    while cur.next != self.__head:        cur = cur.next        if cur.item == item:            return True    return False

最后功能测试如下:

if __name__ == "__main__":    ll = SinCycLinkedlist()    ll.add(1)    ll.add(2)    ll.append(3)    ll.insert(2,4)    ll.insert(4,5)    ll.insert(0,6)    print ("length:",ll.length())    ll.travel()    print (ll.search(3))    print (ll.search(7))    ll.remove(1)    print ("length:", ll.length())    ll.travel()

运行结果如下:

链表运行结果如图所示

上传代码之后, 缩进可能会有点小问题, 注意一定要注意缩进

node 获取表单数据 为空_数据结构与算法(python)单向循环链表相关推荐

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

    链表 数据表的构建需要预先知道数据的大小来申请连续的存储空间, 而在进行扩充的时候又需要进行数据的搬迁, 使用起来不是很灵活. 链表结构可以充分利用计算机内存空间, 实现灵活的内存动态管理. 简单来说 ...

  2. node 获取表单数据 为空_像声明类型一样写表单——基础功能

    从最简单的开始实现,先看一个最简单的场景 先实现这一部分. 首先,我们要遵循一个基本原则,尽量写视图无关的代码. 所以我们把整套代码分成两部分: Core:核心部分,没有任何 React 相关代码的数 ...

  3. node 获取表单数据 为空_程序员:数据结构和算法,中序线索化二叉树

    1.中序线索化二叉树   创建如上的二叉树,线索化二叉树时,根据指定的遍历方式得到的节点的访问顺序,一个节点前面的节点,叫做前驱节点,一个节点后面的节点,叫做后继节点.   线索化二叉树的规则:   ...

  4. node 获取表单数据 为空_寻offer之JS数据结构与算法 -- 栈

    栈 栈是一个线性结构,在计算机中是一种相当常见的数据结构. 栈与数组对比 我们知道数组是一种线性结构,并且可以在数组的任意位置插入和删除数据.但是有时候,我们为了实现某些功能,必须对这种任意性加以限制 ...

  5. python获取表单数据的代码_使用flask和python从html表单获取表单数据

    我正在尝试在按下submit时从文本字段中获取表单数据,以便将其放入json格式并作为另一个页面访问json数据,该页面将是localhost:5000/info.每次我试图用request.form ...

  6. node 获取表单数据 为空_Java实现数据结构之【链表】

    链表相比于前几个章节讲的数据结构而言,是一个真正的动态数据结构也是一个最简单的动态数据结构,我们在后面还会接触更多的动态数据结构,所以对链表有一个理解非常好的基础,就能够更加容易的学习后面更加复杂的数 ...

  7. mooc数据结构与算法python版期末测验_中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案...

    中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案 更多相关问题 采用fopen()函数打开文件,支持文件读取的参数有: [简答题]简单阐述高分子材料热-机械特征及成型加工的关系,并 ...

  8. 数据结构python课后答案_数据结构与算法:Python语言描述 1~5章课后习题

    数据结构与算法:Python语言描述 1~5章课后习题 发布时间:2018-07-19 20:42, 浏览次数:1885 , 标签: Python MarkDown语法写的,不知道为啥上传到CSDN不 ...

  9. 获取用户列表为空_数据结构和算法(Golang实现)(15)常见数据结构-列表

    列表 一.列表 List 我们又经常听到 列表 List 数据结构,其实这只是更宏观的统称,表示存放数据的队列. 列表 List:存放数据,数据按顺序排列,可以依次入队和出队,有序号关系,可以取出某序 ...

最新文章

  1. 【Java】Cloneable 接口讲解 (包含浅拷贝与深拷贝不一样的实现讲解)
  2. R语言ggplot2可视化:ggplot2使用geom_mark_ellipse函数进行椭圆形圈定(注释)特定的数据簇或组
  3. 一个简单的用Python写抽奖程序
  4. java正则hitend,Java Matcher hitEnd()用法及代码示例
  5. mysql的驱动connect放在哪里_Python连接数据库两种方法,QSqlDatabase,pymmsql,驱动名...
  6. 动态规划(一)入门例子
  7. Qtum量子链漏洞赏金计划正式开启
  8. gb-heima/order 项目 处理
  9. navicat导入成功但是没有数据_数据库能建立成功,但是还报错,应该怎么处理...
  10. abaqus实例手册_《ABAQUS 6.14超级学习手册》——1.5 ABAQUS帮助文档
  11. 概念:蓝筹主板创业板新三板科创板
  12. Matlab2018b新特性介绍以及R2018b+waijung blockst 百度云下载链接
  13. 冬季好去处七彩蝴蝶园,温暖如春彩蝶纷飞
  14. 岭回归实现鲍鱼年龄预测 MATLAB实现
  15. 太原网络营销师郭文军揭秘2016营销如何做?
  16. 【2020.11.4 洛谷团队赛 普及组】T1 U138644 小Biu的礼物
  17. linux中一些好玩的程序安装
  18. 关于佳能打印机墨盒的一些操作
  19. CD4046和CD4518B 组成的 100倍倍频器
  20. tim服务器运行出错,解决QQ/TIM在Sandboxie中无法运行

热门文章

  1. python3:利用SMTP协议发送QQ邮件+附件
  2. 2022-2028年中国动力电池回收行业投资分析及前景预测报告
  3. linux下卸载自带jdk,重新安装jre运行环境
  4. MySQL 学习笔记(9)— 事务控制语句、事务属性以及并发和隔离级别
  5. C++ primer 第七章之 友元函数与友元类
  6. 02---控制移动底座1
  7. Servlet中的配置 web.xml
  8. ORA-00942:表或视图不存在(低级错误)
  9. hbase RPCServer源码分析
  10. 我要学ASP.NET MVC 3.0(一): MVC 3.0 的新特性