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 七种邮件内容发送方法实例
Apr 22 Python
Python发送http请求解析返回json的实例
Mar 26 Python
python读取图片并修改格式与大小的方法
Jul 24 Python
Tesserocr库的正确安装方式
Oct 19 Python
python3 爬取图片的实例代码
Nov 06 Python
Python判断一个三位数是否为水仙花数的示例
Nov 13 Python
浅谈Python在pycharm中的调试(debug)
Nov 29 Python
ubuntu16.04升级Python3.5到Python3.7的方法步骤
Aug 20 Python
pycharm 添加解释器的方法步骤
Aug 31 Python
2020版Python学习路线图(附学习资料)
Sep 15 Python
python读写数据读写csv文件(pandas用法)
Dec 14 Python
python学习之panda数据分析核心支持库
May 07 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
PHP中break及continue两个流程控制指令区别分析
2011/04/18 PHP
php后台多用户权限组思路与实现程序代码分享
2012/02/13 PHP
php strnatcmp()函数的用法总结
2013/11/27 PHP
PHP 实现浏览记录并按日期分组
2017/05/11 PHP
脚本吧 - 幻宇工作室用到js,超强推荐expand.js
2006/12/23 Javascript
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
jquery 面包屑导航 具体实现
2013/06/05 Javascript
Javascript学习笔记之 对象篇(一) : 对象的使用和属性
2014/06/24 Javascript
谈谈impress.js初步理解
2015/09/09 Javascript
学习使用grunt来打包JavaScript和CSS程序的教程
2016/01/04 Javascript
js中字符串编码函数escape()、encodeURI()、encodeURIComponent()区别详解
2016/04/01 Javascript
详解JSON1:使用TSQL查询数据和更新JSON数据
2016/11/21 Javascript
javascript replace()第二个参数为函数时的参数用法
2016/12/26 Javascript
微信小程序 解析网页内容详解及实例
2017/02/22 Javascript
Node.js+Express+MySql实现用户登录注册功能
2017/07/10 Javascript
vue项目打包后打开页面空白解决办法
2018/06/29 Javascript
python网络编程学习笔记(九):数据库客户端 DB-API
2014/06/09 Python
在Python的Django框架中编写错误提示页面
2015/07/22 Python
详解Python中的变量及其命名和打印
2016/03/11 Python
python的exec、eval使用分析
2017/12/11 Python
Python wxpython模块响应鼠标拖动事件操作示例
2018/08/23 Python
简单了解python的break、continue、pass
2019/07/08 Python
Django接收自定义http header过程详解
2019/08/23 Python
浅谈Python中的字符串
2020/06/10 Python
Html5获取高德地图定位天气的方法
2019/12/26 HTML / CSS
西班牙购买行李箱和背包网站:Maletas Greenwich
2019/10/08 全球购物
简单说说tomcat的配置
2013/05/28 面试题
学前班教师的自我鉴定
2013/12/05 职场文书
2014年教师培训的自我评价
2014/01/03 职场文书
工程招投标邀请书
2014/01/26 职场文书
招聘与培训专员岗位职责
2014/01/30 职场文书
党员干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
pandas 实现将NaN转换为None
2021/05/14 Python
一文彻底理解js原生语法prototype,__proto__和constructor
2021/10/24 Javascript
ant design vue的form表单取值方法
2022/06/01 Vue.js
Android RecyclerView实现九宫格效果
2022/06/28 Java/Android