python实现单链表、双链表、反转链表(二)

news2024/11/24 8:50:47

一、链表概述

链表是有元素组成的数据结构,每个元素都是单独对象,包含数据和指针信息

链表中的每个元素称为节点,如下所示,第一个节点称为Head(头节点),为链表的入口点,如果链表为空,则Head指向None,链表的最后一个节点指向None
在这里插入图片描述

如上图所示,链表是动态数据结构,无法直接访问数据,搜索任何项都需要从Head开始,必须遍历每个引用才能获取节点信息,链表占用更多内存

二、单链表

单链表是只包含数据和指向下一个引用的数据结构,最后一个节点对象没有引用

定义一个Node类,包括数据data和引用下一个引用reference, 默认下一个reference为None

每创建一个Node类, 将上一个Node类的reference指向当前创建,遍历链表需要从第一个节点开始,如presentNode = objNode1,依次获取当前节点的下一个引用,即为遍历,分配变量presentNode之后, 最后一个节点包含指针值,将推出while循环,因为指针值为None,代码实现如下所示

class Node:
    def __init__(self, data=None):
        """
        创建Node类,包括data(值)和reference(下一个指针)
        :param data:
        """
        self.data = data
        self.reference = None


if __name__ == '__main__':
    objNode1 = Node(1)
    objNode2 = Node(2)
    objNode3 = Node(3)
    objNode4 = Node(4)
    objNode1.reference = objNode2
    objNode2.reference = objNode3
    objNode3.reference = objNode4
    presentNode = objNode1
    while presentNode:
        print("当前Node值为:", presentNode.data)
        presentNode = presentNode.reference

将遍历信息封装,同时创建Linked_list类,目的是 对Node信息进行管理和操作,定义Linked_list类, 保存头节点位置,同时定义指针信息,如下图所示:
在这里插入图片描述

代码如下所示

class Node:
    def __init__(self, data=None):
        """
        创建Node类,包括data(值)和reference(下一个指针)
        :param data:
        """
        self.data = data
        self.reference = None


class Linked_list:
    def __init__(self):
        self.head = None

    def recursive(self):
        """
        定义遍历节点类
        :return:
        """
        presentNode = self.head
        while presentNode:
            print("当前Node值为:", presentNode.data)
            presentNode = presentNode.reference


if __name__ == '__main__':
    objNode1 = Node(1)
    objNode2 = Node(2)
    objNode3 = Node(3)
    objNode4 = Node(4)
    linkObj = Linked_list()
    linkObj.head = objNode1
    linkObj.head.reference = objNode2
    objNode2.reference = objNode3
    objNode3.reference = objNode4
    linkObj.recursive()

如果在链表添加头节点,只需令linkObj.head = new_node和new_node.reference = objNode1

如方法 insert_at_head(data),

  • 首先需要创建一个新节点,此时并未指向任何信息

  • 将当前新节点引用指向当前链表的头节点

  • 然后将头节点指针指向当前节点,即可完成新节点添加

def insert_at_head(self, data):
    """
    链表头部添加新数据
    :param data:
    :return:
    """
    new_data = Node(data)
    # 此处奇妙在,新节点的引用,指向当前链表的头节点,然后在将头节点指针前移,指向新节点即可
    new_data.reference = self.head
    self.head = new_data

如果在链表添加尾节点,需要遍历整个链表,找出当前尾节点,然后将当前尾节点引用,指向新的节点

def insert_at_end(self, data):
    """
    链表尾部添加新数据
    :param data:
    :return:
    """
    new_data = Node(data)
    presentNode = self.head
    while presentNode:
        presentNode = presentNode.reference
    presentNode.reference = new_data

在两个节点之间插入新节点,需要先获取当前节点的引用节点,并把引用节点赋值给待添加节点,同时将当前节点的引用指向待添加节点

def insert_at_middle(self, insert_node, data):
    """
    在insert_node节点后添加新节点
    :param insert_node:
    :param data:
    :return:
    """
    new_node = Node(data)
    new_node.reference = insert_node.reference
    insert_node.reference = new_node

从链表删除节点

A->B->C

A.reference = B

B.reference = C

C.reference = D

删除B节点,则需遍历链表,当到达指向节点B的节点A时,将该值替换为存储在节点B的指针值,节点A指向节点C, 节点B从链表删除

def remove_node(self, remove_obj):
    """
    删除remove_obj节点信息
    :param remove_obj:
    :return:
    """
    presentNode = self.head
    while presentNode:
        if presentNode.reference == remove_obj:
            presentNode.reference = remove_obj.reference
            break
        presentNode = presentNode.reference

三、双链表

双向链表包含3个部分,指向前一个节点指针、数据和指向下一个节点指针,如下图所示:
在这里插入图片描述

双向链表支持从前向后和从后向前遍历,从头开始,使用next移动到下一个节点,从尾开始,使用prev移动到上一个节点,代码如下所示

def recursiveAfter(self):
    """
    从后向前遍历
    :return:
    """
    presentNode = self.tail
    while presentNode.prev:
        print("从前向后遍历,当前值value=", presentNode.data)
        presentNode = presentNode.prev

def recursiveFront(self):
    """
    从后向前遍历
    :return:
    """
    presentNode = self.head
    while presentNode:
        print("从后向前遍历,当前值value=", presentNode.data)
        presentNode = presentNode.next

双向链表尾部追加节点,需要确保追加节点的prev指针指向上一个节点信息

def appendNode(self, data):
    """
    在尾部添加节点
    :param data:
    :return:
    """
    new_data = Node(data)
    presentNode = self.head
    while presentNode:
        presentNode = presentNode.next
    presentNode.next = new_data
    new_data.prev = presentNode

删除节点信息,需要遍历双向链表两次,首先从链表头部开始使用next向后遍历,遇到删除对象,将当前节点的next更改为删除对象之后的节点,同时从后向前遍历,再次遇到删除对象,将当前节点的prev值更改为其之前的节点

def removeNode(self, removeObj):
    """
    删除节点需要遍历两边链表
    :param removeObj:
    :return:
    """
    presentNode = self.head
    # 从前向后删除
    while presentNode:
        if presentNode.next == removeObj:
            presentNode.next = removeObj.next
            break
        presentNode = presentNode.next
    # 从后向前删除
    presentNodeTail = self.tail
    while presentNodeTail:
        if presentNodeTail.prev == removeObj:
            presentNodeTail.prev = removeObj.prev
            break
        presentNodeTail = presentNodeTail.prev

四、反向链表

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

反向列表的实现思路是

  • 保存上一个节点的节点信息

  • 反转节点指向,将当前节点的next指向上一个节点,比如原链表:1->2->3时,应改为3->2->1->NULL

  • 继续处理后面的节点

    如下图所示
    在这里插入图片描述

代码实现思路,如下所示

def reverse(self):
    """
    1->2->3->None
    3->2->1->None
    :return:
    """
    previous = None
    # 头节点
    presentNode = self.head
    # 下一个节点信息
    while presentNode:
        # 获取下一个节点
        nextVal = presentNode.reference
        # 将当前节点的next指向上一个节点
        presentNode.reference = previous
        previous = presentNode
        presentNode = nextVal
    # 最后一个节点赋值为头节点
    self.head = previous

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

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

相关文章

Vue.js 比较重要知识点总结二

概述 vue3 组合式API生命周期钩子函数有变化吗?Composition API 与 Options API 有什么区别?watch 和 watchEffect 的区别?vue2 如何升级到 vue3 ? vue3 组合式API生命周期钩子函数有变化吗? 选项式API 和 组合式API 生命周期…

Java的继承性

1.为什么要有类的继承性?(继承性的好处) ① 减少了代码的冗余,提高了代码的复用性② 便于功能的扩展③ 为之后多态性的使用,提供了前提 2.子类继承父类以后有哪些不同? 2.1体现: 一旦子类A继承父类B以…

汇编基础学习

1. 利用ldr向寄存器里面写较大数据,和设置寄存器的某些位 2. 这个lable 不对呢 验证宏值加载到寄存器里是正确的。 pc 的地址是0x80594 当前pc指针加上宏定义值的地址值。 3 打印字符串 字符串加载了8个字节到寄存器里面, 如何调试打印出来呢&#xff1…

数据库设计的原则有哪些

数据库设计是程序开发的核心部分,标准的数据库设计原则和步骤能有效提高开发进度和效率。 数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据&#xf…

RK3588平台开发系列讲解(驱动基础篇)中断相关函数

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、获取中断号相关函数二、申请中断函数三、free_irq 函数四、中断处理函数五、中断使能和禁止函数沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Linux 中断有专门的中断子系统,其实现原理很复杂,但是驱…

Git详解——安装、使用、搭建、IDEA集成

Git 看目录,越往后面越重要 目录一、git是什么?二、为什么要使用Git?三、版本控制工具四、git下载安装以及环境配置五、git基本命令六、git项目搭建七、远程仓库怎么搞?git,gitlab,github,gitee区别八、idea集成Git 一、Git是什…

HBase2.2.2安装(单机、伪分布)

系列文章目录 Ubuntu常见基本问题 Hadoop3.1.3安装(单机、伪分布) Hadoop集群搭建 HBase2.2.2安装(单机、伪分布) Zookeeper集群搭建 文章目录 系列文章目录前置条件一、HBase2.2.2安装二、配置环境变量1、问题 三、单机模式1、修…

浅谈数字化

一、数字化转型 数字化转型(Digital transformation)是建立在数字化转换(Digitization)、数字化升级(Digitalization)基础上,进一步触及公司核心业务,以新建一种商业模式为目标的高…

仙人掌之歌——权力的游戏(3)

像疯子一样死去 陈速没想到李通是在香山深处一所疗养院里休养,军方的岗位森严,进去还得把身份证押在门卫室。李通穿着病号服悠哉地晃过来把陈速领了进去。 “通哥,这儿真是个好地方啊。” 陈速由衷地赞叹着,望着大院里古树参天&…

九、Spring Cloud—gateway网关

一、引言 每个微服务都需和前端进行通信,解决每个微服务请求时的鉴权、限流、权限校验、跨域等逻辑,放在一个统一的地方进行使用。 在微服务架构中,网关是一个重要的组件,它作为系统的入口,负责接收所有的客户端请求…

Shiro高级及SaaS-HRM的认证授权

Shiro高级及SaaS-HRM的认证授权 Shiro在SpringBoot工程的应用 Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密。越来越多的企业使用Shiro作为项目的安全框架,保证项目的平稳运行。 在之…

前端042_图表展现_自适应

自适应 当缩小窗口时,饼图和柱状图不会自动自适应,会被遮挡住。因为 ECharts 本身并不是自适应的,当你父级容器的宽度发生变化的时候需要手动调用它的 .resize() 方法。 其中 vue-element-admin项目中已经实现了自适应效果,只要将对应代码拷贝引用即可。将 vue-element-adm…

Java中的this、package、import

this 在Java中,this的作用和其词义很接近。 它在方法内部使用,即这个方法所属对象的引用; 它在构造器内部使用,表示该构造器正在初始化的对象。 this 可以调用类的属性、方法和构造器 什么时候使用this关键字呢&#xff…

使用kettle进行日志分析

分析日志是一个大数据分析中较为常见的场景。在Unix类操作系统里,Syslog广泛被应用于系统或者应用的日志记录中。Syslog通常被记录在本地文件内,比如Ubuntu内为/var/log/syslog文件名,也可以被发送给远程Syslog服务器。Syslog日志内一般包括产…

机构的专属的线上招生 教学小程序搭建教程

小程序已经成为了很多教育机构的招生、推广重要渠道之一。相比于传统的网站或APP而言,小程序更加轻量级,更加易于传播和分享。在小程序搭建过程中,无需编写复杂的代码,只需要根据模板进行简单的操作,就可以轻松打造自己…

【Web开发技术】JWT令牌技术(信息安全)

文章目录 一、描述二、依赖三、配置四、java文件中的准备五、开始使用 一、描述 说到JWT令牌技术,就需要提到cookie和session两种技术。这两种技术在跨域问题(计算机网络的知识,百度可以搜到,就回归重点)上存在一定的局…

《智能新工厂规划白皮书》下 | “四步”规划智能工厂

中国制造业有着最大制造产能、最强配套能力和最大消费市场三个无可比拟的优势,随着产能升级,众企业的新工厂会开展智能工厂规划布局,从而实现降本减耗、提高效益的经营目标,以增强企业市场竞争力。 新工厂规划时,企业…

【GitHub已开源】某博热点事件评论数据分析与用户情感分析平台完整项目

找遍全网无奈只能自己开发某博热点评论数据爬取与用户情感分析平台,这就是技术人的创新! 最近想看一下微博热点评论的用户人群情感趋势,想到的就是去爬取某博的评论数据,然后进行一个可视化的情感分析。想想吧,这个项目…

RPC核心原理

大家好,我是易安,今天我们一起来研究下RPC的核心原理。 什么是RPC? RPC的全称是Remote Procedure Call,即远程过程调用。简单解读字面上的意思,远程肯定是指要跨机器而非本机,所以需要用到网络编程才能实现…

用Gmail邮箱注册任天堂日本区账号

任天堂是一家日本公司,日区的任天堂可以买到常驻的任亏券,兑换任天堂第一方游戏,而且经常搞活动,可以买到低价的游戏。 首先进入任天堂官网 https://accounts.nintendo.com/register 注册账号 比如我的Gmail邮箱为 zhaooleegma…