Python实现双向链表


Posted in Python onMay 25, 2022

单向链表和环形链表都只是单向的,只能单向遍历,不能根据后面的节点获取前面的节点,除非进行反转操作。

双向链表每个节点都有两个指针,这两个指针分别指向前后两个节点,这样就可以从任意一个节点从两个方向获取其他的所有节点,非常方便。但是由于每个节点有两个指针,所以双向链表比较消耗空间。

在设计双向链表时,通常会加上一个链表头指针,该链表头指针的数据字段不存放任何数据。

双向链表的可以是环形的,也可以不是环形的,如果是环形的话,那么最后一个节点的一个指针将指向链表头,链表头的一个指针将指向最后一个节点;如果不是环形的话,那么最后一个节点的一个指针和链表头的一个指针都将指向None。

我在这里实现的是一个环形的双向链表,这样我就可以从链表头开始,从两个方向中任意选择一个方向来进行操作。

我在这里主要实现了环形双向链表的:双向新增,双向遍历,双向插入,双向删除。

Python实现双向链表

如图为双向环形链表示意图,每一个节点都被两个指针所指向,同时每个节点也指向了两个节点。

实现代码如下:

class Player:
    """节点类"""
    def __init__(self):
        """初始化姓名,分数,指针"""
        self.name = ''
        self.score = 0
        self.rlink = None
        self.llink = None
 
 
def ergodic(head, num=None, is_print=False, left=False):
    """遍历函数,num是遍历到哪一个位置序号,is_print是否触发打印方法,left表示是否由head开始往左遍历"""
    ptr = head
    count = 0
    while True:
        if num == count:
            break
 
        if not left:
            if ptr.rlink != head:
                ptr = ptr.rlink
            else:
                break
        else:
            if ptr.llink != head:
                ptr = ptr.llink
            else:
                break
        count += 1
        if is_print:
            print('No.'+str(count), ptr.llink.name if ptr.llink != head else 'head', '<---',
                  ptr.name, ptr.score, '--->', ptr.rlink.name if ptr.rlink != head else 'head')
    return ptr  # 返回遍历完成后的最后一个节点
 
 
head = Player()  # 初始化一个链表头指针,不用来存放任何数据
head.rlink = head  # 初始化右指针
head.llink = head  # 初始化左指针
 
 
while True:
    select = input("(1).新增   (2).查看   (3).插入   (4).删除   (5).离开\n输入:")
    if select == "1":  # 新增节点,分为右新增和左新增
        direction = input("(1).右新增   (2).左新增\n输入:")
        if direction not in ("1", "2"):
            print("输入错误")
            continue
        new_data = Player()
        new_data.name = input("姓名:")
        new_data.score = input("分数:")
        if direction == "1":  # 右新增
            ptr = ergodic(head)  # 从head开始向右遍历获取最后一个节点
            ptr.rlink = new_data
            new_data.llink = ptr
            new_data.rlink = head
            head.llink = new_data
        else:  # 左新增
            ptr = ergodic(head, left=True)  # 从head开始向左遍历获取最后一个节点
            ptr.llink = new_data
            new_data.rlink = ptr
            new_data.llink = head
            head.rlink = new_data
 
    elif select == "2":  # 遍历查看所有节点,分为右遍历和左遍历
        direction = input("(1).右遍历   (2).左遍历\n输入:")
        if direction == "1":  # 右遍历
            ergodic(head, is_print=True)
        elif direction == "2":  # 左遍历
            ergodic(head, is_print=True, left=True)
        else:
            print("输入错误")
 
    elif select == '3':  # 插入节点,分为右插入和左插入
        direction = input("(1).右插入   (2).左插入\n输入:")
        if direction not in ("1", "2"):
            print("输入错误")
            continue
        try:
            num = int(input("请输入需要插入的节点位置序号:"))  # 输入序号必须是大于0的正整数,如果输入大于最后一个节点的序号则插入到最后一个节点之后
            if num < 1:
                print("输入必须为大于0的正整数")
                continue
        except ValueError:
            print("输入有误")
            continue
        insert_data = Player()
        insert_data.name = input("姓名:")
        insert_data.score = input("分数:")
        if direction == "1":  # 右插入
            ptr = ergodic(head, num - 1)  # 获取需要插入位置的前一个节点,新插入的节点就在这个节点的后面
            insert_data.llink = ptr
            insert_data.rlink = ptr.rlink
            ptr.rlink = insert_data
            insert_data.rlink.llink = insert_data
        else:  # 左插入
            ptr = ergodic(head, num - 1, left=True)
            insert_data.rlink = ptr
            insert_data.llink = ptr.llink
            ptr.llink = insert_data
            insert_data.llink.rlink = insert_data
 
    elif select == '4':  # 删除节点,分为右删除和左删除
        direction = input("(1).右删除   (2).左删除\n输入:")
        if direction not in ("1", "2"):
            print("输入错误")
            continue
        try:
            num = int(input("请输入需要删除的节点位置序号:"))  # 输入序号必须是大于0的正整数,如果输入大于最后一个节点的序号则删除最后一个节点
            if num < 1:
                print("输入必须为大于0的正整数")
                continue
        except ValueError:
            print("输入有误")
            continue
        if direction == "1":  # 右删除
            ptr = ergodic(head, num)  # 获取需要删除的节点
        else:  # 左删除
            ptr = ergodic(head, num, left=True)
        ptr.llink.rlink = ptr.rlink
        ptr.rlink.llink = ptr.llink
 
    elif select == '5':
        print("成功离开")
        break
    else:
        print("输入错误,请重试")

部分运行效果如下:

Python实现双向链表

以上就是本文的全部内容,希望对大家的学习有所帮助。


Tags in this post...

Python 相关文章推荐
python+selenium实现登录账户后自动点击的示例
Dec 22 Python
浅谈Python实现2种文件复制的方法
Jan 19 Python
Python中pillow知识点学习
Apr 30 Python
如何用python写一个简单的词法分析器
Dec 18 Python
pytorch逐元素比较tensor大小实例
Jan 03 Python
Django使用Celery加redis执行异步任务的实例内容
Feb 20 Python
matlab灰度图像调整及imadjust函数的用法详解
Feb 27 Python
python GUI库图形界面开发之PyQt5切换按钮控件QPushButton详细使用方法与实例
Feb 28 Python
使用Python开发个京东上抢口罩的小实例(仅作技术研究学习使用)
Mar 10 Python
神经网络训练采用gpu设置的方式
Mar 03 Python
Python中else的三种使用场景
Jun 16 Python
Python使用plt.boxplot()函数绘制箱图、常用方法以及含义详解
Aug 14 Python
python区块链持久化和命令行接口实现简版
May 25 #Python
python区块链实现简版工作量证明
May 25 #Python
pycharm无法安装cv2模块问题
May 20 #Python
python中 Flask Web 表单的使用方法
May 20 #Python
Python OpenGL基本配置方式
May 20 #Python
Python面试不修改数组找出重复的数字
May 20 #Python
Python 中面向接口编程
May 20 #Python
You might like
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
值得分享的php+ajax实时聊天室
2016/07/20 PHP
使用PHPStorm+XDebug搭建单步调试环境
2017/11/19 PHP
PHP常见加密函数用法示例【crypt与md5】
2019/01/27 PHP
用javascript实现给图片加链接
2007/08/15 Javascript
js获取单元格自定义属性值的代码(IE/Firefox)
2010/04/05 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
2012/05/23 Javascript
Js数组排序函数sort()介绍
2015/06/08 Javascript
javascript实现自动填写表单实例简析
2015/12/02 Javascript
js跨浏览器的事件侦听器和事件对象的使用方法
2015/12/17 Javascript
详解Bootstrap创建表单的三种格式(一)
2016/01/04 Javascript
javascript产生随机数方法汇总
2016/01/25 Javascript
js实现拖拽功能
2017/03/01 Javascript
Easyui Datagrid自定义按钮列(最后面的操作列)
2017/07/13 Javascript
Vue配合iView实现省市二级联动的示例代码
2018/07/27 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
Vue项目vscode 安装eslint插件的方法(代码自动修复)
2020/04/15 Javascript
python基础教程之popen函数操作其它程序的输入和输出示例
2014/02/10 Python
Python实现检测服务器是否可以ping通的2种方法
2015/01/01 Python
Python实现网站注册验证码生成类
2017/06/08 Python
python中for循环输出列表索引与对应的值方法
2018/11/07 Python
python中的函数递归和迭代原理解析
2019/11/14 Python
python获取依赖包和安装依赖包教程
2020/02/13 Python
Python是怎样处理json模块的
2020/07/16 Python
如何基于Django实现上下文章跳转
2020/09/16 Python
python实现scrapy爬虫每天定时抓取数据的示例代码
2021/01/27 Python
突破canvas语法限制 让他支持链式语法
2012/12/24 HTML / CSS
资产评估专业学生的自我鉴定
2013/11/14 职场文书
历史系自荐信范文
2013/12/24 职场文书
医院护士见习期自我鉴定
2014/04/10 职场文书
计划生育证明书写要求
2014/09/17 职场文书
汽车机电维修工求职信
2014/09/30 职场文书
小学思品教学反思
2016/02/20 职场文书
民政局2016年“六一”儿童节慰问活动总结
2016/04/06 职场文书
python cv2图像质量压缩的算法示例
2021/06/04 Python
JS中如何优雅的使用async await详解
2021/10/05 Javascript