Python----数据结构(双向链表:节点,是否为空,长度,遍历,添加,删除,查找,循环链表)

一、双向链表

1.1、概念 

        双向链表是一种链表数据结构,每个节点除了包含指向下一个节点的指针外,还包含指向前一个节点的指针。这种特性使得在双向链表中,可以从任意一个节点开始,向前或向后遍历链表。 

1.2、特点 

• 既可以从头遍历到尾, 又可以从尾遍历到头,也就是链表相连的过程是双向的。

• 一个节点既有向前连接的引用, 也有一个向后连接的引用。

• 双向链表可以有效的解决单向链表中提到的问题。

1.3、双向链表的基本操作

1.3.1、节点的创建

class Node:def __init__(self, data):# 初始化节点,包含数据和指向下一个节点和前一个节点的指针self.data = data  # 节点存储的数据self.next = None  # 指向下一个节点的指针self.prev = None  # 指向前一个节点的指针

1.3.2、初始化双向链表

    def __init__(self, node=None):# 初始化链表,头指针指向第一个节点(默认为None)self.__head = node  # 链表的头节点

1.3.3、is_empty()链表是否为空

    def is_empty(self):# 检查链表是否为空return self.__head is None  # 如果头节点为None,则链表为空

1.3.4、length()链表长度

    def length(self):# 计算链表的长度current = self.__head  # 从头节点开始count = 0  # 初始化计数器while current is not None:  # 遍历链表count += 1  # 计数器加一current = current.next  # 移动到下一个节点return count  # 返回链表的长度

1.3.5、travel()遍历整个链表

    def travel(self):# 遍历链表并打印每个节点的数据current = self.__head  # 从头节点开始while current is not None:  # 遍历链表print(current.data)  # 打印当前节点的数据current = current.next  # 移动到下一个节点

1.3.6、add(data)链表头部添加元素

    def add(self, data):# 在链表头部添加新节点new_node = Node(data)  # 创建新节点if self.is_empty():  # 如果链表为空self.__head = new_node  # 头节点指向新节点else:new_node.next = self.__head  # 新节点的下一个指向当前头节点self.__head.prev = new_node  # 当前头节点的前一个指向新节点self.__head = new_node  # 更新头节点为新节点

 

1.3.7、append(data)链表尾部添加元素

    def append(self, data):# 在链表尾部添加新节点new_node = Node(data)  # 创建新节点if self.is_empty():  # 如果链表为空self.__head = new_node  # 头节点指向新节点else:current = self.__head  # 从头节点开始while current.next is not None:  # 遍历到链表的最后一个节点current = current.nextcurrent.next = new_node  # 最后一个节点的下一个指向新节点new_node.prev = current  # 新节点的前一个指向最后一个节点

 

1.3.8、insert(pos, data)指定位置添加元素

    def insert(self, pos, data):# 在指定位置插入新节点if pos >= self.length():  # 如果位置超出范围self.append(data)  # 添加到尾部elif pos <= 0:  # 如果位置小于等于0self.add(data)  # 添加到头部else:new_node = Node(data)  # 创建新节点current = self.__head  # 从头节点开始count = 0# 遍历到插入新节点的位置while count < pos:current = current.next  # 移动到下一个节点count += 1# 在正确的位置插入新节点new_node.prev = current.prev  # 新节点的前一个指向当前节点的前一个new_node.next = current  # 新节点的下一个指向当前节点if current.prev:  # 确保 current.prev 不是 Nonecurrent.prev.next = new_node  # 前一个节点的下一个指向新节点current.prev = new_node  # 当前节点的前一个指向新节点

 

1.3.9、remove(data)删除节点

    def remove(self, data):# 移除链表中指定数据的节点current = self.__head  # 从头节点开始pre = None  # 用于跟踪当前节点的前一个节点while current is not None:  # 遍历链表if current.data == data:  # 找到要删除的节点if current == self.__head:  # 如果是头节点self.__head = current.next  # 更新头指针if self.__head:  # 如果新的头节点不为空self.__head.prev = None  # 更新新头节点的前一个指针else:pre.next = current.next  # 将前一个节点的next指向当前节点的nextif current.next:  # 如果当前节点的下一个节点不为空current.next.prev = pre  # 更新下一个节点的前一个指针break  # 找到并删除后退出循环else:pre = current  # 移动前一个节点指针current = current.next  # 移动到下一个节点

1.3.10、search(data) 查找节点是否存在

    def search(self, data):# 查找链表中是否存在指定数据current = self.__head  # 从头节点开始while current is not None:  # 遍历链表if current.data == data:  # 找到数据return True  # 找到数据,返回Truecurrent = current.next  # 移动到下一个节点return False  # 遍历完成未找到数据,返回False

完整代码 

class Node:def __init__(self, data):# 初始化节点,包含数据和指向下一个节点和前一个节点的指针self.data = data  # 节点存储的数据self.next = None  # 指向下一个节点的指针self.prev = None  # 指向前一个节点的指针class LinkList:def __init__(self, node=None):# 初始化链表,头指针指向第一个节点(默认为None)self.__head = node  # 链表的头节点def is_empty(self):# 检查链表是否为空return self.__head is None  # 如果头节点为None,则链表为空def length(self):# 计算链表的长度current = self.__head  # 从头节点开始count = 0  # 初始化计数器while current is not None:  # 遍历链表count += 1  # 计数器加一current = current.next  # 移动到下一个节点return count  # 返回链表的长度def travel(self):# 遍历链表并打印每个节点的数据current = self.__head  # 从头节点开始while current is not None:  # 遍历链表print(current.data)  # 打印当前节点的数据current = current.next  # 移动到下一个节点def add(self, data):# 在链表头部添加新节点new_node = Node(data)  # 创建新节点if self.is_empty():  # 如果链表为空self.__head = new_node  # 头节点指向新节点else:new_node.next = self.__head  # 新节点的下一个指向当前头节点self.__head.prev = new_node  # 当前头节点的前一个指向新节点self.__head = new_node  # 更新头节点为新节点def append(self, data):# 在链表尾部添加新节点new_node = Node(data)  # 创建新节点if self.is_empty():  # 如果链表为空self.__head = new_node  # 头节点指向新节点else:current = self.__head  # 从头节点开始while current.next is not None:  # 遍历到链表的最后一个节点current = current.nextcurrent.next = new_node  # 最后一个节点的下一个指向新节点new_node.prev = current  # 新节点的前一个指向最后一个节点def insert(self, pos, data):# 在指定位置插入新节点if pos >= self.length():  # 如果位置超出范围self.append(data)  # 添加到尾部elif pos <= 0:  # 如果位置小于等于0self.add(data)  # 添加到头部else:new_node = Node(data)  # 创建新节点current = self.__head  # 从头节点开始count = 0# 遍历到插入新节点的位置while count < pos:current = current.next  # 移动到下一个节点count += 1# 在正确的位置插入新节点new_node.prev = current.prev  # 新节点的前一个指向当前节点的前一个new_node.next = current  # 新节点的下一个指向当前节点if current.prev:  # 确保 current.prev 不是 Nonecurrent.prev.next = new_node  # 前一个节点的下一个指向新节点current.prev = new_node  # 当前节点的前一个指向新节点def remove(self, data):# 移除链表中指定数据的节点current = self.__head  # 从头节点开始pre = None  # 用于跟踪当前节点的前一个节点while current is not None:  # 遍历链表if current.data == data:  # 找到要删除的节点if current == self.__head:  # 如果是头节点self.__head = current.next  # 更新头指针if self.__head:  # 如果新的头节点不为空self.__head.prev = None  # 更新新头节点的前一个指针else:pre.next = current.next  # 将前一个节点的next指向当前节点的nextif current.next:  # 如果当前节点的下一个节点不为空current.next.prev = pre  # 更新下一个节点的前一个指针break  # 找到并删除后退出循环else:pre = current  # 移动前一个节点指针current = current.next  # 移动到下一个节点def search(self, data):# 查找链表中是否存在指定数据current = self.__head  # 从头节点开始while current is not None:  # 遍历链表if current.data == data:  # 找到数据return True  # 找到数据,返回Truecurrent = current.next  # 移动到下一个节点return False  # 遍历完成未找到数据,返回Falseif __name__ == '__main__':linklist = LinkList()  # 创建链表实例linklist.add(10)  # 添加节点10linklist.add(20)  # 添加节点20linklist.append(100)  # 在尾部添加节点100linklist.add(30)  # 添加节点30linklist.add(40)  # 添加节点40linklist.insert(3, 505)  # 在位置3插入节点505print(linklist.length())  # 输出链表长度print('*****************')linklist.travel()  # 遍历链表并打印节点数据

二、循环链表

        循环链表是一种特殊的链表,其最后一个节点的指针不是指向None,而是指向链表的头节点。这样就形成了一个环形结构。

class Node:def __init__(self, data):# 初始化节点,包含数据和指向下一个节点的指针self.data = dataself.next = Noneself.prev = Noneclass LinkList:def __init__(self):# 初始化链表,头指针指向第一个节点(默认为None)self.__head = Nonedef is_empty(self):# 检查链表是否为空return self.__head is Nonedef length(self):# 计算链表的长度if self.is_empty():return 0current = self.__headcount = 1  # 从头节点开始计数while current.next != self.__head:  # 遍历到回到头节点count += 1current = current.nextreturn countdef travel(self):# 遍历链表并打印每个节点的数据if self.is_empty():returncurrent = self.__headwhile True:print(current.data)current = current.nextif current == self.__head:  # 回到头节点时停止breakdef add(self, data):# 在链表头部添加新节点new_node = Node(data)if self.is_empty():self.__head = new_nodenew_node.next = new_node  # 指向自己,形成循环new_node.prev = new_node  # 指向自己,形成循环else:new_node.next = self.__headnew_node.prev = self.__head.prevself.__head.prev.next = new_node  # 更新旧头节点的前一个节点的nextself.__head.prev = new_node  # 更新头节点的前一个指向新节点self.__head = new_node  # 更新头节点为新节点def append(self, data):# 在链表尾部添加新节点new_node = Node(data)if self.is_empty():self.__head = new_nodenew_node.next = new_node  # 指向自己,形成循环new_node.prev = new_node  # 指向自己,形成循环else:tail = self.__head.prev  # 找到尾节点tail.next = new_nodenew_node.prev = tailnew_node.next = self.__head  # 新节点的next指向头节点self.__head.prev = new_node  # 更新头节点的前一个指向新节点def insert(self, pos, data):# 在指定位置插入新节点if pos >= self.length():  # 使用 >= 来处理追加到末尾的情况self.append(data)  # 如果位置超出范围,添加到尾部elif pos <= 0:self.add(data)  # 如果位置小于等于0,添加到头部else:new_node = Node(data)current = self.__headcount = 0# 遍历到插入新节点的位置while count < pos:current = current.next  # 移动到下一个节点count += 1# 在正确的位置插入新节点new_node.prev = current.prev  # 新节点的前一个指向当前节点的前一个new_node.next = current  # 新节点的下一个指向当前节点# 更新周围节点的指针current.prev.next = new_node  # 前一个节点的next指向新节点current.prev = new_node  # 当前节点的前一个指向新节点def remove(self, data):# 移除链表中指定数据的节点if self.is_empty():returncurrent = self.__headwhile True:if current.data == data:if current == self.__head and current.next == self.__head:self.__head = None  # 只有一个节点的情况else:current.prev.next = current.next  # 前一个节点的next指向当前节点的nextcurrent.next.prev = current.prev  # 后一个节点的prev指向当前节点的previf current == self.__head:  # 如果是头节点,更新头指针self.__head = current.nextbreakcurrent = current.nextif current == self.__head:  # 遍历完成未找到数据breakdef search(self, data):# 查找链表中是否存在指定数据if self.is_empty():return Falsecurrent = self.__headwhile True:if current.data == data:return True  # 找到数据,返回Truecurrent = current.nextif current == self.__head:  # 遍历完成未找到数据breakreturn False  # 返回False

三、思维导图

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VScode内接入deepseek包过程(本地部署版包会)

目录 1. 首先得有vscode软件 2. 在我们的电脑本地已经部署了ollama&#xff0c;我将以qwen作为实验例子 3. 在vscode上的扩展商店下载continue 4. 下载完成后&#xff0c;依次点击添加模型 5. 在这里可以添加&#xff0c;各种各样的模型&#xff0c;选择我们的ollama 6. 选…

投资组合风险管理

投资组合风险管理 市场风险 信用风险流动性风险风险指标收益率波动率最大回撤 α \alpha α&#xff08;詹森指数&#xff09;&#xff0c; β \beta β卡玛比率月胜率上/下行捕获比夏普比率索提诺比率经风险调整的收益率&#xff08;&#x1d440;2&#xff09;特雷诺比率信息…

Mongodb数据管理

Mongodb数据管理 1.登录数据库&#xff0c;查看默认的库 [rootdb51~]# mongo> show databases; admin 0.000GB config 0.000GB local 0.000GB> use admin switched to db admin > show tables system.version > admin库&#xff1a;admin 是 MongoDB 的管理…

GTP3 大模型

GTP3 大模型 模型架构训练核心思想 GTP3 : OpenAI 在 2020 年 5 月发布 GPT-3&#xff0c;发表 Language Models are Few-Shot Learner理念&#xff1a;Few-Shot 思想 , 用少量样本微调&#xff0c;让模型更准确 参数 : 最大模型 : 1750 亿参数多头 Transformer : 96 层Head…

神经网络实验——MLP

目录 1 目的 2 方法 3 源代码 4 结果 1 目的 ①熟悉 Python 的输入输出流; ②学会使用 matplotlib进行图像可视化; ③掌握神经网络的基本原理&#xff0c;学会使用 sklearn 库中的 MLPClassifier 函数构建基础的多层感知机神经网络分类器; ④学会使用网格查找进行超参数优…

Cursor 无限续杯

最近DeepSeek官网无法访问&#xff0c;导致DeepSeekCLine绑定的API Key也无法使用了。那么&#xff0c;除了DeepSeek&#xff0c;还有没有其他好用的AI编程工具呢&#xff1f;答案当然是Cursor&#xff01;不过&#xff0c;由于各种原因一直没有用上Cursor&#xff0c;也不知道…

Windows本地部署DeepSeek

文章目录 一、准备工作1、准备服务器2、准备APP 二、部署deepseek-r11、脚本部署2、脚本部署 三、ChatBox集成 一、准备工作 1、准备服务器 本案例使用Windows电脑 2、准备APP Download Ollama Download Chatbox 二、部署deepseek-r1 1、脚本部署 双击安装完Ollama,默认…

QML 自定义矩形框Rectangle,实现四个边框自定义大小

一、自定义矩形 效果图 边框大小为&#xff1a;左2 上2 右5 下10 简单来说&#xff0c;就是定义两个矩形&#xff0c;一个在外边一个在内部&#xff1b; 再通过设置他们的边距&#xff0c;即可设置相应的边框宽度&#xff1b; 1.编码 新建空的qml文件 MyRectangle.qml im…

筛选相同项

# import os # import pandas as pd# # 文件路径&#xff0c;根据实际情况修改 # file_path_1 rC:\Users\Administrator\Desktop\python\文件1.xlsx # file_path_2 rC:\Users\Administrator\Desktop\python\文件2.xlsximport os import pandas as pd# 获取当前脚本所在的目录…

MVTEC数据集笔记

前言 网上的博客只有从论文里摘出的介绍&#xff0c;没有数据集文件详细的样子&#xff0c;下载数据集之后&#xff0c;对数据集具体的构成做一个补充的笔记。 下载链接&#xff1a;https://ai-studio-online.bj.bcebos.com/v1/7d4a3cf558254bbaaf4778ea336cb14ed8bbb96a7f2a…

Bom详解和Dom详解

Javascript的数据类型 1.BOM(浏览器对象模型)1.1window对象(1)全局作用域&#xff1a;(2)窗口属性&#xff1a;(3)弹窗和对话框&#xff1a;(4)定时器&#xff1a;(5)导航和历史&#xff1a;(6)打开和关闭窗口&#xff1a; 1.2navigator对象(1)浏览器信息属性&#xff1a;(2)浏…

Android 虚拟机与ClassLoader类加载笔记

1 Android虚拟机 在介绍Android的虚拟机之前&#xff0c;我们先来看一下JVM虚拟机之下&#xff0c;我们的class文件的字节码指令的Demo&#xff1a; public class Demo {public static void test() {int a 1;int b 2;int c a b;} } 将Demo.class文件使用命令&#xff1a…

STM32 HAL库USART串口DMA IDLE中断编程:避坑指南

HAL_UART_Receive接收最容易丢数据了,STM32 HAL库UART查询方式实例 可以考虑用中断来实现,但是HAL_UART_Receive_IT还不能直接用,容易数据丢失,实际工作中不会这样用,STM32 HAL库USART串口中断编程&#xff1a;演示数据丢失, 需要在此基础优化一下. STM32F103 HAL库USART串口…

NBT群落物种级丰度鉴定新方法sylph

文章目录 简介为什么选择Sylph&#xff1f;Sylph的工作原理 Install使用解析成gtdb格式sylph 能做什么&#xff1f;sylph 不能做什么&#xff1f;ANI定义如何使用 sylph-utils 生成包含分类信息的配置文件耗时&#xff1a;66个样本耗时1h 转成easymicroplot可用数据 简介 Sylp…

VLM 系列——Qwen2.5 VL——论文解读——前瞻(源码解读)

引言 20250212苹果突然被爆将与阿里巴巴合作为中国 iPhone 用户开发人工智能功能。苹果从 2023 年就已经开始测试各类中国头部 AI 大厂开发的 AI 模型。去年&#xff0c;原本选定百度作为主要合作伙伴&#xff0c;但双方的合作并不顺利&#xff0c;百度为“Apple Intelligence”…

DeepSeek R1原理

文章目录 DeepSeek R1原理强化学习介绍Policy ModelCritic ModelReward Model三者关系智能体包含的内容环境包含的内容 知识蒸馏简介数据蒸馏Logits 蒸馏特征蒸馏 训练流程DeepSeek-R1-Zero 训练策略与价值设计奖励方式训练模板**实验观察到模型自我进化**缺点 DeepSeek-R1 训练…

如何使用DeepSeek + PlantUML/Mermaid 生成专业图表

目录 一、工具简介 1.1 DeepSeek简介 1.2 PlantUML简介 1.3 Mermaid在线工具简介 二、在DeepSeek中生成Mermaid语法 2.1 编写提示词 2.2 示例输出 2.3 访问Mermaid在线编辑器 三、在DeepSeek中生成PlantUML语法 3.1 编写提示词 3.2 示例输出 3.3 访问PlantUML在线编…

开源多商户商城源码最新版_适配微信小程序+H5+APP+PC多端

在数字化时代&#xff0c;电子商务已经成为各行业不可或缺的一部分&#xff0c;开源多商户商城源码为中小企业和个人开发者提供了快速搭建和定制电商平台的利器。分享一款最新版的开源多商户商城源码&#xff0c;它能够适配微信小程序、H5、APP和PC等多个端口&#xff0c;满足商…

PHP基础部分

但凡是和输入、写入相关的一定要预防别人植入恶意代码! HTML部分 语句格式 <br> <hr> 分割符 <p>插入一行 按住shift 输入! 然后按回车可快速输入html代码(VsCode需要先安装live server插件) html:<h1>标题 数字越大越往后</h1> <p…

短视频矩阵碰一碰发视频源码技术开发,支持OEM

在短视频矩阵碰一碰发视频的技术开发中&#xff0c;前端设计是直接面向用户的关键部分&#xff0c;它不仅决定了用户体验的好坏&#xff0c;还对整个系统的可用性和吸引力起着重要作用。本文将深入探讨在这一技术开发中前端设计的要点、流程与关键技术。 一、前端设计的整体架构…