【3】数据结构的双向链表章

news2025/4/2 22:35:05

目录标题

    • 双向链表的定义
      • 双向链表的初始化
      • 双向链表的创建
      • 插入操作
      • 删除操作
    • 双向链表总代码与调试

双向链表的定义

  • 结点结构组成:数据域(data)、指针域(pre)、指针域(next)。其中,

    • data存储结点的值
    • pre直接前驱结点的地址
    • next直接后继结点的地址
  • 定义:在单链表中的每一个结点中再增加一个指向其前驱的指针域,该中方式形式的链表成为双向链表。

  • 结点示意图
    在这里插入图片描述

  • 双向链表逻辑结构示意图
    在这里插入图片描述

  • 代码定义双向链表结点

class Node:
    """
    定义双向链表结点类型
    """
    def __init__(self, data):
        # 存储结点中的数据域
        self.data = data
        # 指向后继结点的指针域next
        self.next = None
        # 指向前驱结点的指针域pre
        self.pre = None

双向链表的初始化

  • 初始化双向链表
class DLinkedList:
    """
    双向链表的定义
    """
    def __init__(self):
        """
        双向链表的初始化
        """
        self.head = Node(None)
  • 判断双向链表是否为空
    def isEmpty(self):
        """
        判断双向链表是否为空表
        :return: true or false
        """
        # 如果头结点的next域为none,则返回True,否则返回false
        return self.head.next is None
  • 求双向链表的长度
    def getLength(self):
        """
        获取双向链表的长度
        :return: 当前双向链表中元素的个数
        """
        # length用于计算双向链表的长度
        length = 0
        # 声明cur指针,用于遍历表
        cur = self.head.next
        while cur != None:
            length += 1
            cur = cur.next
        return length
  • 展示双向链表
    def display(self):
        """
        遍历双向链表,进行扫描展示
        :return:
        """
        if self.isEmpty():
            print("当前双向链表为空")
            return
        print("双向链表的元素为:", end="")
        # 循环遍历
        cur = self.head.next
        while cur != None:
            print(cur.data, end="")
            cur =cur.next
        print()

双向链表的创建

    def append(self, data):
        """
        建立双向链表
        :param data: 待插入的元素
        :return:
        """
        # 查找尾结点
        rear = self.head
        while rear.next != None:
            rear = rear.next
        # 创建新结点
        newNode = Node(data)
        # 将尾结点的next指针指向新结点
        rear.next = newNode
        # 将新结点的pre指针指向尾结点
        newNode.pre = rear

插入操作

  • 核心思想

    • 在双向链表第index个结点之前插入一个新的结点,通过四个操作调整指针的指向;
    • 1.设置指针,指向第index个结点,将新结点的前驱指针指向指针cur所指向的结点的前驱结点
    • 2.将指针cur所指向的结点的前驱结点的后继指针指向新结点
    • 3.将新结点的后继指针指向cur所指向的结点
    • 4.将指针cur所指向的结点的前驱指针指向新结点
  • 插入示意图
    在这里插入图片描述

  • 代码定义插入法

    def insert(self, index, data):
        """
        双向链表中任意位置插入元素
        :param index: 待插入的元素位置
        :param data: 待插入元素的值
        :return:
        """
        i = 1
        # 声明指针cur,用于遍历双向链表
        cur = self.head
        # 遍历
        while cur != None and i !=index + 1:
            cur = cur.next
            i += 1
        # index非法情况
        if cur == None or i > self.getLength():
            raise IndexError('index 非法')
        # 创建新结点
        newNode = Node(data)
        # 将新结点的前驱指针指向指针cur所指向的结点的前驱结构
        newNode.pre = cur.pre
        # 将指针cur所指向的结点的前驱结点的后继指针指向新结点
        cur.pre.next = newNode
        # 将新结点的后继指针指向cur所指向的结点
        newNode.next = cur
        # 将指针cur所指向的结点的前驱指针指向新结点
        cur.pre = newNode

删除操作

  • 核心思想
    • 设置局域指针cur,遍历表,直到该指针指向要删除结点;
    • 将指针cur所指向结点的前驱结点的next指针指向指针cur所指向结点的后继结点
    • 将指针cur所指向结点的后继结点的pre指针指向指针cur指向结点的前驱结点
  • 删除示意图
    在这里插入图片描述
  • 代码定义删除法
    def delete(self, index):
        """
        在双向链表中任意位置删除元素
        :param index: 待删除元素的位置
        :return: 被删除的元素
        """
        # 若双向链表为空,抛出异常
        if self.isEmpty():
            raise IndexError('当前为空表!')
        # 找到需要删除结点的前一个结点
        i = 1
        cur = self.head
        while cur != None and i != index + 1:
            cur = cur.next
            i += 1
        # 若index非法
        if cur == None or i > self.getLength():
            raise IndexError('index 非法')
        # 获取被删除元素
        data = cur.data
        # 将指针cur所指向结点的前驱结点的next指针指向指针cur所指向结点的后继结点
        cur.pre.next = cur.next
        # 将指针cur所指向结点的后继结点的pre指针指向指针cur指向结点的前驱结点
        cur.next.pre = cur.pre
        return data

双向链表总代码与调试

  • 双向链表:单链表的一个缺点是无法快速访问前驱结点,当查找某一元素,需要再次从头开始遍历查找,便有了双向链表。
  • 相对于单链表,双向链表复杂一些,它多了一个前驱指针,插入与删除操作相对更复杂与易出错。
# 5.双向链表的实现
class Node:
    """
    定义双向链表结点类型
    """
    def __init__(self, data):
        # 存储结点中的数据域
        self.data = data
        # 指向后继结点的指针域next
        self.next = None
        # 指向前驱结点的指针域pre
        self.pre = None

class DLinkedList:
    """
    双向链表的定义
    """
    def __init__(self):
        """
        双向链表的初始化
        """
        self.head = Node(None)
    def isEmpty(self):
        """
        判断双向链表是否为空表
        :return: true or false
        """
        # 如果头结点的next域为none,则返回True,否则返回false
        return self.head.next is None
    def getLength(self):
        """
        获取双向链表的长度
        :return: 当前双向链表中元素的个数
        """
        # length用于计算双向链表的长度
        length = 0
        # 声明cur指针,用于遍历表
        cur = self.head.next
        while cur != None:
            length += 1
            cur = cur.next
        return length
    def display(self):
        """
        遍历双向链表,进行扫描展示
        :return:
        """
        if self.isEmpty():
            print("当前双向链表为空")
            return
        print("双向链表的元素为:", end="")
        # 循环遍历
        cur = self.head.next
        while cur != None:
            print(cur.data, end="")
            cur =cur.next
        print()
    # 建立双向链表
    def append(self, data):
        """
        建立双向链表
        :param data: 待插入的元素
        :return:
        """
        # 查找尾结点
        rear = self.head
        while rear.next != None:
            rear = rear.next
        # 创建新结点
        newNode = Node(data)
        # 将尾结点的next指针指向新结点
        rear.next = newNode
        # 将新结点的pre指针指向尾结点
        newNode.pre = rear
    def insert(self, index, data):
        """
        双向链表中任意位置插入元素
        :param index: 待插入的元素位置
        :param data: 待插入元素的值
        :return:
        """
        i = 1
        # 声明指针cur,用于遍历双向链表
        cur = self.head
        # 遍历
        while cur != None and i !=index + 1:
            cur = cur.next
            i += 1
        # index非法情况
        if cur == None or i > self.getLength():
            raise IndexError('index 非法')
        # 创建新结点
        newNode = Node(data)
        # 将新结点的前驱指针指向指针cur所指向的结点的前驱结构
        newNode.pre = cur.pre
        # 将指针cur所指向的结点的前驱结点的后继指针指向新结点
        cur.pre.next = newNode
        # 将新结点的后继指针指向cur所指向的结点
        newNode.next = cur
        # 将指针cur所指向的结点的前驱指针指向新结点
        cur.pre = newNode

    def delete(self, index):
        """
        在双向链表中任意位置删除元素
        :param index: 待删除元素的位置
        :return: 被删除的元素
        """
        # 若双向链表为空,抛出异常
        if self.isEmpty():
            raise IndexError('当前为空表!')
        # 找到需要删除结点的前一个结点
        i = 1
        cur = self.head
        while cur != None and i != index + 1:
            cur = cur.next
            i += 1
        # 若index非法
        if cur == None or i > self.getLength():
            raise IndexError('index 非法')
        # 获取被删除元素
        data = cur.data
        # 将指针cur所指向结点的前驱结点的next指针指向指针cur所指向结点的后继结点
        cur.pre.next = cur.next
        # 将指针cur所指向结点的后继结点的pre指针指向指针cur指向结点的前驱结点
        cur.next.pre = cur.pre
        return data


if __name__ == '__main__':
    # print('PyCharm')
    
    # 1.双向链表初始化
    list = DLinkedList()
    list.display()
    # 2.创建双向链表
    for i in range(10):
        list.append(chr(ord('A') + i))
    print('尾插入操作,', end="")
    list.display()
    # 3.获取双向链表的长度
    length = list.getLength()
    print('双向链表的长度为:', length)
    # 4.在双向链表中任意位置插入元素
    list.insert(2, 'Y')
    list.display()
    # 4.在双向链表中任意位置删除元素
    data = list.delete(2)
    print("被删除元素为:", data)
    list.display()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2326818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯杯赛-日期模拟

知识点 处理日期 1. 按天枚举日期:逐天遍历起始日期到结束日期范围内的每个日期。 2. 处理闰年:正确判断闰年条件。闰年定义为:年份 满足以下任意一个条件:(闰年的2月只有29天) 满足下面一个条件就是闰年 1> 是 400 的倍数…

搭建开源笔记平台:outline

折腾的意义 为什么要自己搭建一个笔记平台?没理由,就是突然想试试。有时候突然有个想法,搜了一下正好有合适的方案,就顺手试一下。 其实已经有很多成熟的笔记软件,例如Notion/OneNote,但谁不想要一个数据完…

Unity编辑器功能及拓展(2) —Gizmos编辑器绘制功能

Unity中的Gizmos功能是用于在场景视图中绘制辅助图形或图标的工具,帮助开发者在编辑模式下直观调试和可视化游戏对象的位置、范围、方向等信息。 一.定义概述 Gizomsd 概述 Gizoms是Unity提供的一个API,或者叫做一个工具类,包含一系列静态…

电脑屏幕亮度随心控,在Windows上自由调整屏幕亮度的方法

调整电脑屏幕的亮度对于保护视力和适应不同环境光线条件非常重要。无论是在白天强光下还是夜晚昏暗环境中,合适的屏幕亮度都能让您的眼睛更加舒适。本文中简鹿办公小编将向您介绍几种在 Windows 系统中调整屏幕亮度的方法。 方法一:使用快捷键 大多数笔…

presto行转列

presto的行列转换和spark、hive一样也是通过外链语句实现的,只不过语法和关键子有点不同,如下 with tmp1 as (select 1,2,3 as a1,4,5,6 as a2 ) select * from tmp1 cross join unnest(split(tmp1.a1, ,),split(tmp1.a2, ,) ) as b(a1s,a2s) 结果如下

51c自动驾驶~合集15

我自己的原文哦~ https://blog.51cto.com/whaosoft/11720657 #DRAMA 首个基于Mamba的端到端运动规划器(新加坡国立) 运动规划是一项具有挑战性的任务,在高度动态和复杂的环境中生成安全可行的轨迹,形成自动驾驶汽车的核心能…

拼多多 anti-token unidbg 分析

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 版本7.3-7.4 都试过加密没什…

【Git】5 个分区的切换方式及示例

目录 1. **工作区(Working Directory)**2. **缓存区(Stage/Index)**3. **本地仓库(Local Repository)**4. **远程仓库(Remote Repository)**5. **贮藏区(Stash&#xff0…

Java高频面试之并发编程-02

hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶 面试官:进程和线程的区别是什么? 1. 资源分配与独立性 进程: 独立性:每个进程拥有独立的内存…

openwebui和keycloak集成,使用keycloak的用户名和密码登录

1,实现效果 使用keycloak定义的用户名和密码,直接登录openwebui 2,实现原理 keycloak中用户信息中包含用户名和密码,以及email。 使用keycloak中的用户名和密码登录之后,会用email创建一个openwebui的账号。之后每次…

【区块链安全 | 第八篇】多签机制及恶意多签

部分参考:慢雾科技 文章目录 为什么需要多签多签机制Tron钱包下的恶意多签Tron 钱包多签权限分类Tron 多签机制的运作方式 恶意多签的过程黑客通过多签机制控制账户黑客剥夺用户权限,完全控制账户 恶意多签成因 在区块链中,多签(M…

二月公开赛Web-ssrfme

目录 环境搭建 题目分析 分析代码 解题过程 Redis未授权访问 寻找Flag 环境搭建 进入含有docker-compose.yml的文件内,拉取容器镜像 docker-compose up -d 题目分析 访问容器地址172.25.254.200:8091查看题目 分析代码 url通过GET请求访问界面&#xff0c…

告别枯燥工作,走向自动化

嘿,小伙伴们!今天给你们介绍两款超实用的RPA办公自动化软件,用它们,再也不用像机器一样做重复劳动啦,超省时间! 工具名称:影刀RPA(类似产品,八爪鱼 RPA,操作上…

可信数据空间:构筑安全可控数据流通

前言:可信数据空间是一种数据基础设施,发展可信数据空间是全国及各地数据基础设施建设的重要方面。国内数据空间的探索和实践仍然数据探索阶段。本期分享:可信数据空间构筑安全可控数据流通,包括可信数据空间技术介绍、如何助力数…

Zookeeper特性与节点数据类型

数据结构和监听机制 CP 文件系统形式存储 观察者模式监听节点数据变化、 临时节点客户端超时或发生异常节点就会删除 2888同步数据 3888选举端口 1.什么是Zookeeper ZooKeeper 是一个开源的分布式协调框架,是Apache Hadoop 的一个子项目,主要用来…

处理 Linux 信号:进程控制与异常管理的核心

个人主页:chian-ocean 文章专栏-Linux 前言: 在 Linux 操作系统中,信号是用于进程间通信的一种机制,能够向进程发送通知,指示某些事件的发生。信号通常由操作系统内核、硬件中断或其他进程发送。接收和处理信号是 Li…

【蓝桥杯每日一题】4.1

🏝️专栏: 【蓝桥杯备篇】 🌅主页: f狐o狸x "今日秃头刷题,明日荣耀加冕!" 今天我们来练习二分算法 不熟悉二分算法的朋友可以看:【C语言刷怪篇】二分法_编程解决算术问题-CSDN博客 …

分享系列项目的基础项目

本人分享了一系列的框架项目,它们共同需要依赖这个公共基础,结构如下图所示: 其中: audit: JPA的审计信息基础类auth:认证授权相关类config: 包括redis配置,client中token配置,openai文档配置…

为 MinIO AIStor 引入模型上下文协议(MCP)服务器

Anthropic 最近宣布的模型上下文协议 (MCP) 将改变我们与技术交互的方式。它允许自然语言通信替换许多任务的复杂命令行语法。不仅如此,语言模型还可以总结传统工具的丰富输出,并以人类可读的形式呈现关键信息。MinIO 是世界领先的…

数据结构实验1.1: 顺序表的操作及其应用

这里写自定义目录标题 一、实验目的二、注意事项三、实验内容(一)问题描述(二)基本要求 四,操作步骤(一)使用visual studio集成环境编写程序 五,示例代码六,运行效果 一、…