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的绘图工具matplotlib使用实例
Jul 03 Python
在Python的Django框架下使用django-tagging的教程
May 30 Python
用Python写冒泡排序代码
Apr 12 Python
浅谈五大Python Web框架
Mar 20 Python
Python处理时间日期坐标轴过程详解
Jun 25 Python
python3.7 使用pymssql往sqlserver插入数据的方法
Jul 08 Python
pygame编写音乐播放器的实现代码示例
Nov 19 Python
TensorFlow绘制loss/accuracy曲线的实例
Jan 21 Python
Tensorflow: 从checkpoint文件中读取tensor方式
Feb 10 Python
基于python 等频分箱qcut问题的解决
Mar 03 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
Mar 10 Python
pandas抽取行列数据的几种方法
Dec 13 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获取文件大小的方法
2014/02/26 PHP
为PHP安装imagick时出现Cannot locate header file MagickWand.h错误的解决方法
2014/11/03 PHP
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
javascript forEach通用循环遍历方法
2010/10/11 Javascript
JQuery通过Ajax提交表单并返回结果
2011/07/31 Javascript
jquery学习笔记 用jquery实现无刷新登录
2011/08/08 Javascript
Javascript的各种节点操作实例演示代码
2012/06/27 Javascript
JS刷新框架外页面七种实现代码
2013/02/18 Javascript
js关闭当前页面(窗口)的几种方式总结
2013/03/05 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
Hallo.js基于jQuery UI所见即所得的Web编辑器
2016/01/26 Javascript
AngularJS向后端ASP.NET API控制器上传文件
2016/02/03 Javascript
Node.js编写爬虫的基本思路及抓取百度图片的实例分享
2016/03/12 Javascript
微信小程序 教程之wxapp视图容器 swiper
2016/10/19 Javascript
详解jQuery lazyload 懒加载
2016/12/19 Javascript
JavaSctit 利用FileReader和滤镜上传图片预览功能
2017/09/05 Javascript
js最简单的双向绑定实例讲解
2018/01/02 Javascript
element-ui多文件上传的实现示例
2019/04/10 Javascript
jQuery控制input只能输入数字和两位小数的方法
2019/05/16 jQuery
javascript 原型与原型链的理解及实例分析
2019/11/23 Javascript
深入webpack打包原理及loader和plugin的实现
2020/05/06 Javascript
Python解析nginx日志文件
2015/05/11 Python
Python实现抢购IPhone手机
2018/02/07 Python
Pandas 数据处理,数据清洗详解
2018/07/10 Python
Python分支语句与循环语句应用实例分析
2019/05/07 Python
pycharm如何实现跨目录调用文件
2020/02/28 Python
Python小白垃圾回收机制入门
2020/06/09 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
2020/08/19 Python
个人授权委托书范本
2014/09/14 职场文书
2014年前台个人工作总结
2014/11/14 职场文书
办公室岗位职责范本
2015/04/11 职场文书
咖啡厅里的创业计划书
2019/08/21 职场文书
导游词之鲁迅祖居
2019/10/17 职场文书
Flask response响应的具体使用
2021/07/15 Python
js前端图片加载异常兜底方案
2022/06/21 Javascript