Python数据结构(链表)
Python数据结构(链表)
单向链表
单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

表元素域elem用来存放具体的数据
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点
节点实现
class node(object):def __init__(self,item):# __item存放的是数据元素self.item = item# __next是下一个节点的表示self.next = None
单链表的操作
class node(object):def __init__(self,item):# __item存放的是数据元素self.item = item# __next是下一个节点的表示self.next = Noneclass SingleLinkList(object):def __init__(self,node=None):self.head = node # 定义头节点,默认值为Nodedef is_empty(): #链表是否为空return self.head == None:def length(): #链表长度cur = self.head #cur游标表当前的节点,用来移动遍历节点count = 0while cur != None:count += 1cur = cur.nextreturn countdef travel(): #遍历整个链表cur = self.headwhile cur != None:print(cur.item, end=" ")cur = cur.nextprint("")def get_all(self):#查找整个链表数据cur = self.headres = []while True:#遍历整个链表,并转成列表形式if cur.next == None:if cur.item:res.append(cur.item)breakelse:if cur.item:res.append(cur.item)cur = cur.nextreturn resdef reverse_printing(self):res = self.get_all()#获取列表形式所有链表数据ret =res[::-1]#反转列表return retdef reverse(self):#反转链表res = self.reverse_printing()#获取逆序的列表形式链表sign1 = self.head#创建游标while True:#遍历整个链表,断开各连接,没有指向的数据会被垃圾回收if sign1.next == None:breaksign2 = sign1.nextsign1.next = Nonesign1 = sign2sign = self.headfor ele in res:#根据逆序列表形式链表,重新构建链表body = Item(ele)sign.next = bodysign = sign.nextdef ReverseList(self): #反转链表 cur = self.head pre = None while cur: nextNode = cur.next cur.next = pre pre = cur cur = nextNode return pre def add(item): #链表头部添加元素,头插法node = Node(item)node.next = self.headself.head = nodedef append(item): #链表尾部添加元素,尾插法node = Node(item)if self.is_empty():self.head = nodeelse:cur = self.headwhile cur.next != None:cur = cur.nextcur.next = nodedef insert(pos,item): #指定位置添加元素if pos <= 0:self.add(item)elif pos > (self.length()-1):self.append(item)else:pre = self.headcount = 0while count < (pos-1):count += 1pre = pre.next# 当循环退出后,pre指向pos-1的位置node = Node(item)node.next = pre.nextpre.next = nodedef remove(item): #删除节点# 双指针cur = self.headpre = Nonewhile cur != None:if cur.item == item:# 先判断此节点是否为头结点if cur == self.head:self.head = cur.nextelse:pre.next = cur.nextbreakelse:pre = curcur = cur.next# 单指针pre = self.headwhile pre != None:if pre.next.item == item:if pre == self.head:self.head = pre.nextelse:pre.next = pre.next.nextbreakelse:pre = pre.nexdef search(item): #查找节点是否存在cur = self.headwhile cur != None:if cur.item == item:return Trueelse:cur = cur.nextreturn False
链表与顺序表的对比
链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:
| 操作 | 链表 | 顺序表 |
|---|---|---|
| 访问元素 | O(n) | O(1) |
| 在头部插入/删除 | O(1) | O(n) |
| 在尾部插入/删除 | O(n) | O(1) |
| 在中间插入/删除 | O(n) | O(n) |
注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。
单向循环链表
单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点

操作
class Node(object):def __init__(self,item):self.item = itemself.next = Node
class SingleCycleLinkList(object): #单向循环链表def __init__(self,node=Node):self.head = node# 定义头节点if node:node.next = nodedef is_empty(self): #判空return self.head = Nonedef length(self): #链表长度if self.is_empty():return 0cur = self.headcount = 1while cur.next != self.head:count += 1cur = cur.nextreturn countdef travel(self): #遍历链表if self.is_empty():returncur = self.headwhile cur.next != self.next:print(cur.item, end=' -> ')cur = cur.nextprint(cur.item) #尾节点不能进入循环所以要出循环后打印出来def add(self,item): #头插法node = Node(item)if self.is_empty():self.head = nodenode.next = nodeelse:cur = self.headwhile cur.next != self.head:cur = cur.next#退出循环后cur指向尾节点node.next = self.headself.head = nodecur.next = self.head #cur.next = nodedef append(self,item): #尾插法node = Node(item)if self.is_empty():self.head = nodenode.next = nodeelse:cur = self.headwhile cur.next != self.head:cur =cur.nextnode.next = self.headcur.next = nodedef insert(self,pos,item): #在指定位置插入元素if pos < 0:self.add(item)elif pos > (self.length()-1):self.append(item)else:pre = self.headcount = 0while count < (pos-1):count += 1pre = pre.nextnode = Node(item)node.next = pre.nextpre.next = nodedef remove(self,item): #删除节点cur = self.headpre = Nonewhile cur.next != self.head:if cur.item == item;#判断此节点是否为头结点if cur == sef.head:#删除是头结点的情况先找到尾节点rear = self.headwhile rear.next != self.head:rear = rear.nextself.head = cur.nextrear.next = self.headelse:#中间节点pre.next = cur.nextreturnelse:pre = curcur = cur.next#退出循环,cur指向尾节点 if cur.item == item:if cur == self.head:#链表只有一个节点的情况self.head = Noneelse:pre.next = cur.nextdef search(self,item): #查找节点if self.is_empty():return Falsecur = self.headwhile cur.next!= self.head:if cur.item = item:return Trueelse:cur = cur.next#退出循环,cur指向尾节点if cur.item == item:return Truereturn False
双向链表
一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值,而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

操作
class Node(object): #应为前几个方法与单链表都一样用面向对象的思想可以把单链表中的类继承过来"""双链表的节点"""def __init__(self, item):self.item = itemself.next = Noneself.prev = Nonedef is_empty(): #链表是否为空return self.head == None:def length(): #链表长度cur = self.head #cur游标表当前的节点,用来移动遍历节点count = 0while cur != None:count += 1cur = cur.nextreturn countdef travel(): #遍历整个链表cur = self.headwhile cur != None:print(cur.item, end=" ")cur = cur.nextprint("")def add(item): #链表头部添加元素,头插法node = Node(item)node.next = self.headself.head.prev = nodeself.head = nodedef append(item): #链表尾部添加元素,尾插法node = Node(item)if self.is_empty():self.head = nodeelse:cur = self.headwhile cur.next != None:cur = cur.nextcur.next = nodenode.prev = curdef insert(pos,item): #指定位置添加元素if pos <= 0:self.add(item)elif pos > (self.length()-1):self.append(item)else:cur = self.headcount = 0while count < pos:count += 1cur = cur.next# 当循环退出后,cur指向pos的位置node = Node(item)node.next = curnode.prev = cur.prevcur.prev.next = nodecur.prev = nodedef remove(item): #删除节点cur = self.headwhile cur != None:if cur.item == item:if cur == self.head:self.head = cur.nextif cur.next: #判断链表是否只有一个节点cur.next.prev = Noneelse:cur.prev.next = cur.nextif cur.next:cur.next.prev = cur.prevbreakelse:cur = cur.nexdef search(item): #查找节点是否存在cur = self.headwhile cur != None:if cur.item == item:return Trueelse:cur = cur.nextreturn False
相关文章:
Python数据结构(链表)
Python数据结构(链表) 单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向…...
连续/离散的控制系统阶跃测试(包括MATLAB里的step()函数)
阶跃测试 只要是连续时间系统,无论是传递函数还是连续状态空间形式的模型,直接可以用**step()**做阶跃测试;但是对于离散系统而言,不能用step()函数,可以自行编写代码,如下。 1、离散系统:x(k…...
【六:pytest框架介绍】
常见的请求对象requests.get()requests.post()requests.delete()requests.put()requests.request()常见的响应对象reprequests.request()//返回字符串格式数据print(req.text)//返回字节格式数据print(req.content)//返回字典格式数据print(req.json)#状态码print(req.status_c…...
提升医院安全的关键利器——医院安全(不良)事件报告系统源码
医院是人们寻求医疗服务和康复的场所,安全是医院运营的基石。然而,医疗过程中不可避免地会出现不良事件,如药物错误、手术事故等。为了及时发现、评估和解决这些问题,医院安全(不良)事件报告系统应运而生。…...
【瑞吉外卖部分功能补充】
瑞吉外卖部分功能补充 菜品的启售和停售 在浏览器控制台点击对应功能后可以看到前端发送的请求是:http://localhost:9999/dish/status/1?ids1413342036832100354,请求方式为POST。 接收到前端参数后,进行controller层代码补全,…...
react的setState做了什么
1、为什么需要setState setState的作用是帮助我们更改数据的同时并且通知视图进行渲染。因为React并不会绑定视图和state,需要我们手动去更新视图。 2、setState什么时候是同步的,什么时候是异步的 setState这个方法在调用的时候是同步的,…...
ubuntu18.04 RTX3060 rangnet++训练 bonnetal语义分割
代码链接: https://github.com/PRBonn/lidar-bonnetal 安装anaconda环境为 CUDA 11.0(11.1也可以) anaconda环境如下 numpy1.17.2 torchvision0.2.2 matplotlib2.2.3 tensorflow1.13.1 scipy0.19.1 pytorch1.7.1 vispy0.5.3 opencv_python…...
Linux:权限是什么
本篇文章来简单介绍一下Linux操作系统中权限的基本概念和一些操作方法,对Linux权限有一个基本的了解,希望对大家学习Linux有所帮助。 目录 1.权限的概念 2.Linux权限管理 2.1 文件访问者的分类 2.2 文件类型与访问权限(事物属性ÿ…...
uni-app yrkDataPicker 日期和时间选择控件
uni-app 选择日期时间控件有 2 月份有 31 天的问题,一直没有修复,uni-calendar 苹果有选择年份和月份后无法显示问题。自己写了一个,只支持 H5 和微信小程序,其他没有试过。 <template><view class"yrk-data-picke…...
PAM从入门到精通(十九)
接前一篇文章:PAM从入门到精通(十八) 本文参考: 《The Linux-PAM Application Developers Guide》 PAM 的应用开发和内部实现源码分析 先再来重温一下PAM系统架构: 更加形象的形式: 六、整体流程示例 2.…...
apache httpd 多后缀解析漏洞
形成原因 Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令 在有多个后缀的情况下,只要一个文件含有.php后缀的文件即将被识别成PHP文件,没必要是最后一个后缀。利用这个特性,将会造成一个可以绕过上传白名单…...
Flutter ☞ 数据类型
数值类型 int、double、num int 整型,取值通常在 -253 ~ 253 之间 int class double 64-bt(双精度)浮点数,符合 IEEE 754 标准。 double class num 数值类型的基类,int 和 double 都继承自num。 num class 数值转换 // String -> …...
MyBatis-Plus 实战教程一
这里写目录标题 简介快速上手数据库建立创建实体类修改参数引入依赖测试常见注解介绍TableNameTableIdTableField 常见配置仓库地址 简介 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,…...
闭包(函数)
把内部函数通过return扔出去 必要条件...
Go包介绍与初始化:搞清Go程序的执行次序
Go包介绍与初始化:搞清Go程序的执行次序 文章目录 Go包介绍与初始化:搞清Go程序的执行次序一、main.main 函数:Go 应用的入口函数1.1 main.main 函数1.2 main.main 函数特点 二、包介绍2.1 包介绍与声明2.2 非 main包的 main 函数2.3 包的命名…...
Python教程(15)——Python流程控制语句详解
目录 if语句else if语句for循环遍历类型range关键字 while循环break语句continue语句 Python流程控制是Python编程中非常重要的一部分,它用于控制程序的执行流程。Python提供了多种流程控制语句,包括if语句、while循环、for循环、break和continue语句等。…...
JavaScript基础知识16——分支语句
哈喽,大家好,我是雷工。 今天学习JavaScript基础知识的分支语句,以下为学习笔记。 1、程序三大流程控制语句 ○写几句就从上往下执行几句,这种叫做顺序结构; ○有时要根据条件选择执行代码,这种叫分支结构…...
web开发初级工程师学习笔记
web开发初级工程师学习笔记 前端开发工具实验1 VS Code 初体验介绍 前端开发工具 实验1 VS Code 初体验 介绍 VS Code 环境提供的是一个可以在浏览器中使用原生 VS Code 编辑代码的程序。在该环境中,你可以使用到与本地安装近乎一致的 VS Code 程序来编辑代码文件…...
Linux下Samba服务安装及启用全攻略
Linux下Samba服务安装及启用全攻略 前言一、安装SSH Server二、安装Samba Server1.安装net-tool2.建立账号的samba3.windows通过Samba与linux共享文件4.使用远程工具登录Linux 总结 前言 提示:本文详解了在Linux系统下如何安装和启用Samba服务,涵盖了从…...
【C++】引用’‘的深入解析
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
