【数据结构】双向链表、单向循环链表、双向循环链表、栈、链栈
目录
一、双向链表
定义类和封装函数以及测试样例如下:
注意事项:
二、循环链表
单循环列表的类和函数封装如下:
注意事项:
三、双向循环链表
结点类和双循环链表的定义部分
函数封装之判空和尾插
双循环链表遍历
双循环链表尾删
完整测试以及结果:
四、栈
顺序栈
顺序栈本质以及组成
顺序栈的操作
链栈
一、双向链表
对于单向链表而言。只能通过头节点或者第一个节点出发,单向的访问后继节点,每个节点只能记录其后继节点的信息(位置),不能向前遍历。
所以引入双向链表,双向链表可以保持单向链表特点的基础上,让每个节点,既能向后访问后继节点,也可以向前访问前驱节点。
相较于单向链表,我们更多的是在每个结点上加入了一个前驱链接域
定义类和封装函数以及测试样例如下:
class Node(object):def __init__(self,data):self.next = Noneself.prior = Noneself.data = dataclass DoubleLinklist(object):def __init__(self):self.head = Noneself.size = 0def is_empty(self):return self.size == 0def add_head(self,value):node=Node(value)if self.is_empty():self.head = nodeself.size+=1else:node.next = self.headself.head.prior = nodeself.head = nodeself.size += 1def show_me(self):if self.is_empty():print('空表查看不了')else:q = self.headwhile q :print(q.data,end=' ')q = q.nextdef add_anywhere(self,location,value):if location < 1 or location > self.size+1:print('插入失败')else:node = Node(value)if location == 1:self.add_head(value)else:q = self.headi = 1while i< location-1:q = q.nexti += 1if q.next is None:q.next = nodenode.prior = qelse:node.next = q.nextnode.prior = qq.next.prior = nodeq.next = nodeself.size+=1def del_anywhere(self,location):if self.is_empty() or location < 1 or location > self.size:print('删除失败')else:if location == 1:self.head = self.head.nextself.head.prior = Noneelse:q=self.headi =1while i < location :q = q.nexti += 1if q.next :q.prior.next = q.nextq.next.prior = q.priorelse:q.prior.next = Noneself.size -=1def find_node(self,value):if self.is_empty():print('查找失败')else:q = self.headwhile q:if q.data == value:return Trueq = q.nextreturn Falseif __name__ == '__main__':new_l=DoubleLinklist()print('头插')new_l.add_head(50)new_l.add_head(40)new_l.add_head(30)new_l.add_head(20)new_l.add_head(10)new_l.show_me()print()print('任意位置插入')new_l.add_anywhere(1,666)new_l.add_anywhere(7,666)new_l.add_anywhere(3,666)new_l.show_me()print()print('任意位置删除')new_l.del_anywhere(8)new_l.del_anywhere(3)new_l.del_anywhere(1)new_l.show_me()print()print('找是否存在值30')print(new_l.find_node(30))print()
结果如下:
注意事项:
对链表的删除和插入操作我们均要考虑空表、末尾元素、单个元素情况;双循环链表的插入操作 : node.next = q.next
node.prior = q
q.next.prior = node
q.next = node
这四条语句除了第一条的位置不能变动以外(防止丢失结点),后面的操作前后顺序没有强制要求。
二、循环链表
循环链表:就是首尾相连的链表,通过任意一个节点,都能将整个链表遍历一遍
单循环列表的类和函数封装如下:
class Node(object):def __init__(self,data):self.data = dataself.next = Noneclass CirculateLinkList(object):def __init__(self):self.head = Noneself.size = 0def is_empty(self):return self.size == 0def add_tail(self,value):node = Node(value)if self.is_empty():self.head = nodenode.next = nodeelse:q = self.headi = 1while i < self.size:q = q.nexti += 1q.next = nodenode.next = self.headself.size += 1def show_me(self):if self.is_empty():print('空表')elif self.size == 1 :print(self.head.data)else:q = self.headi = 1while i < self.size+1: #q要定位到第一个结点才能遍历完print(q.data,end=' ')q=q.nexti += 1def del_tail(self):if self.is_empty():print('删除失败')elif self.size == 1 :self.head = Noneself.size -=1else:q = self.headi = 1while i < self.size-1 :q = q.nexti+=1q.next = self.headself.size -= 1if __name__ == '__main__':new_l=CirculateLinkList()print('尾插')new_l.add_tail(30)new_l.add_tail(20)new_l.add_tail(10)new_l.show_me()print()print('尾删')new_l.del_tail()new_l.del_tail()new_l.show_me()print()
结果:
注意事项:
基本注意事项不再赘述,这里有个格外要注意的点:
def show_me(self):
if self.is_empty():
print('空表')
elif self.size == 1 :
print(self.head.data)
else:
q = self.head
i = 1
while i < self.size+1: #q要定位到第一个结点才能遍历完
print(q.data,end=' ')
q=q.next
i += 1
while循环要多循环一次,使得q指向第一个结点才能遍历完整
三、双向循环链表
双循环链表同样需要考虑几个点,如何创建,如何增删改查,由于是双向的,那么可以不用像单向的删除操作中一定要找到删除元素前一个位置,可以直接定位到要删除的位置,只需要把前驱后继都重新分配好即可。
结点类和双循环链表的定义部分
class Node(object):def __init__(self,data):self.data=dataself.next=Noneself.prior=Noneclass DoubleCirculateLinkList(object):def __init__(self):self.head=Noneself.size=0
函数封装之判空和尾插
注意:尾插部分要注意分空表和单元素情况
def is_empty(self):return self.size == 0def add_tail(self,value):node=Node(value)if self.is_empty():self.head=nodenode.next=nodenode.prior=nodeelif self.size == 1:self.head.next=nodeself.head.prior=nodenode.next=self.headnode.prior=self.headelse:q=self.headwhile True:q=q.nextif q.next==self.head:breaknode.next=self.headnode.prior=qq.next=nodeself.head.prior=nodeself.size+=1
这里的常规尾插我用到的遍历循环是while True:内部增加一个判断退出的条件来获得末尾结点q
情况全分析完毕整体判断外size+=1即可
双循环链表遍历
遍历涉及到打印,我们用一个变量q来记录,常规情况下要遍历到最后一个结点,但这还不够,要执行的下去循环内的打印语句才行,所以要留意。
def show_me(self):if self.is_empty():print('空表')else:q=self.headwhile True:print(q.data,end=' ')q=q.nextif q ==self.head:break
双循环链表尾删
首先,空表无法删除,单元素删除直接head==None,常规情况可直接遍历到最后一个结点(由于是双向的链表所以不用找倒数第二个结点了),然后将该结点的前驱结点next指向head,head指向的结点的前驱再指向回来即可删除。
def del_tail(self):if self.is_empty():print('空表')elif self.size == 1:self.head = Noneelse:q=self.headwhile True:q=q.nextif q.next==self.head:breakq.prior.next=self.headself.head.prior=q.priorself.size-=1
完整测试以及结果:
class Node(object):def __init__(self,data):self.data=dataself.next=Noneself.prior=Noneclass DoubleCirculateLinkList(object):def __init__(self):self.head=Noneself.size=0def is_empty(self):return self.size == 0def add_tail(self,value):node=Node(value)if self.is_empty():self.head=nodenode.next=nodenode.prior=nodeelif self.size == 1:self.head.next=nodeself.head.prior=nodenode.next=self.headnode.prior=self.headelse:q=self.headwhile True:q=q.nextif q.next==self.head:breaknode.next=self.headnode.prior=qq.next=nodeself.head.prior=nodeself.size+=1def show_me(self):if self.is_empty():print('空表')else:q=self.headwhile True:print(q.data,end=' ')q=q.nextif q ==self.head:breakdef del_tail(self):if self.is_empty():print('空表')elif self.size == 1:self.head = Noneelse:q=self.headwhile True:q=q.nextif q.next==self.head:breakq.prior.next=self.headself.head.prior=q.priorself.size-=1if __name__ == '__main__':new_l=DoubleCirculateLinkList()print('尾插')new_l.add_tail(10)new_l.add_tail(20)new_l.add_tail(30)new_l.add_tail(40)new_l.add_tail(50)new_l.show_me()print()print('尾删')new_l.del_tail()new_l.del_tail()new_l.show_me()print()
四、栈
顺序栈
顺序存储的栈即是顺序栈
顺序栈本质以及组成
本质上:顺序栈是一个只允许在栈顶进行插入和删除操作的顺序表,遵循LIFO
需要使用一个容器存储一个栈,例如列表
顺序栈的操作
这里直接使用内置函数去对栈封装
class Stack(object):def __init__(self):self.data = []def is_empty(self):return self.data == []def push(self,value):self.data.insert(0,value)def pop(self):self.data.pop(0)def show(self):for i in self.data:print(i,end=' ')print()def get_top_value(self):return self.data[0]def get_size(self):return len(self.data)
链栈
既然顺序栈就是对栈顶元素增删的特殊的顺序表,那么链栈就是对栈顶元素增删的特殊的单向链表
这里我的pop不仅实现了删除,而且还增加了额外的返回值
代码如下:
class Node(object):def __init__(self,data):self.data=dataself.next=Noneclass LinkStack(object):def __init__(self):self.size=0self.head=Nonedef is_empty(self):return self.size==0def push(self,value):node=Node(value)node.next=self.headself.head=nodeself.size+=1def pop(self):if self.is_empty():print('空栈')else:q=self.head.dataself.head=self.head.nextself.size-=1return qdef show(self):if self.is_empty():print('空栈')else:q=self.headwhile q:print(q.data,end=' ')q=q.nextdef get_top_value(self):if self.is_empty():return Noneelse:return self.head.datadef get_size(self):return self.size
未完待续(持续跟新中)🏆
相关文章:

【数据结构】双向链表、单向循环链表、双向循环链表、栈、链栈
目录 一、双向链表 定义类和封装函数以及测试样例如下: 注意事项: 二、循环链表 单循环列表的类和函数封装如下: 注意事项: 三、双向循环链表 结点类和双循环链表的定义部分 函数封装之判空和尾插 双循环链表遍历 双循…...

(动画)Qt控件 QProgressBar
文章目录 QProgressBar1. 介绍一、基本特性二、核心属性 2. 代码实现3. 动画效果 QProgressBar 1. 介绍 QProgressBar是Qt框架中的一个控件,主要用于显示进度条,以图形化的方式表示任务的完成进度或操作的进度。 一、基本特性 显示方向:…...

【AI】基础原理
文章目录 前言1. AI 是如何学习的?2. AI 怎么做决定?3. AI 的“大脑”是什么样的?4. AI 为什么会犯错?5. AI 的不同类型总结:AI 的本质是什么? 前言 人工智能(AI)这个词对很多人来说…...

多模态大型语言模型(MLLM)综述
目录 多模态大语言模型的基础 长短期网络结构(LSTM) 自注意力机制 基于Transformer架构的自然语言处理模型 多模态嵌入概述 多模态嵌入关键步骤 多模态嵌入现状 TF-IDF TF-IDF的概念 TF-IDF的计算公式 TF-IDF的主要思路 TF-IDF的案例 训练和微调多模态大语言模…...

计算机的错误计算(一百六十六)
摘要 探讨 MATLAB 关于算式 的计算误差。 例1. 已知 计算 直接贴图吧: 然而,16位的正确结果为 -0.9765626220703239e-21(ISRealsoft 提供)。这样,MATLAB输出的有效数字的错误率为 (16-2)/16 87.5% . 注&…...

typeof 和 as 关键字
在编程语言中,类型系统是确保代码正确性和可维护性的关键。JavaScript和TypeScript作为现代前端开发的两大支柱,它们在处理类型方面有着不同的机制。本文将探讨typeof和as这两个关键字在JavaScript和TypeScript中的应用,帮助开发者更好地理解…...

Python酷库之旅-第三方库Pandas(237)
目录 一、用法精讲 1116、pandas.tseries.offsets.BusinessHour.is_year_end方法 1116-1、语法 1116-2、参数 1116-3、功能 1116-4、返回值 1116-5、说明 1116-6、用法 1116-6-1、数据准备 1116-6-2、代码示例 1116-6-3、结果输出 1117、pandas.tseries.offsets.Cu…...

git提交到远程仓库如何撤回?
git提交到远程仓库如何撤回? 要撤回已经提交到远程仓库的更改,你可以使用以下步骤: 首先,确保你的本地仓库是最新状态。如果不是,请先执行 git pull 来更新你的本地仓库。 使用 git log 查看提交历史,找到你想要撤回…...

微信小程序常用全局配置项及窗口组成部分详解
微信小程序常用全局配置项及窗口组成部分详解 引言 微信小程序作为一种新兴的应用形态,凭借其轻量级、便捷性和丰富的功能,已成为开发者和用户的热门选择。在开发小程序的过程中,了解全局配置项和窗口组成部分是至关重要的。本文将详细介绍微信小程序的常用全局配置项及窗…...

ThingsBoard规则链节点:Azure IoT Hub 节点详解
目录 引言 1. Azure IoT Hub 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 数据传输 3.2 数据分析 3.3 设备管理 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台,提供了设备…...

「Mac玩转仓颉内测版32」基础篇12 - Cangjie中的变量操作与类型管理
本篇将深入探讨 Cangjie 编程语言中的变量操作与类型管理,涵盖变量的定义、作用域、类型推断、常量、变量遮蔽、类型转换等方面的知识。通过这些概念的学习,开发者将更好地理解和灵活掌握变量的使用与管理技巧。 关键词 变量定义类型推断常量变量作用域…...

【Android】RecyclerView回收复用机制
概述 RecyclerView 是 Android 中用于高效显示大量数据的视图组件,它是 ListView 的升级版本,支持更灵活的布局和功能。 我们创建一个RecyclerView的Adapter: public class MyRecyclerView extends RecyclerView.Adapter<MyRecyclerVie…...

麒麟系统性能瓶颈分析
1.使用率,表示资源用于服务的时间或容量百分比。100% 的使用率,表示容量已经用尽或者全部时 间都用于服务。 2. 饱和度,表示资源的繁忙程度,通常与等待队列的长度相关。100% 的饱和度,表示资源无法接受 更多的请求。 3…...

Java二分查找+冒泡排序
二分查找在编程中是用来查找目标元素在有序数组中的位置,并返回目标元素的索引 先给定一个有序数组,在创建一个方法来进行二分 主要思想是:根据数组具有下标的特点来分别计算,最左边的索引,以及最右边的索引,在判断目标元素与中间元素的大小,如果目标元素小于中间元素,我们可…...

(三)手势识别——动作识别应用【代码+数据集+python环境(免安装)+GUI系统】
(三)手势识别——动作识别应用【代码数据集python环境(免安装)GUI系统】 (三)手势识别——动作识别【代码数据集python环境GUI系统】 背景意义 随着互联网的普及和机器学习技术的进一步发展,手…...

大数据实战——MapReduce案例实践
🌟欢迎来到 我的博客 —— 探索技术的无限可能! 🌟博客的简介(文章目录) 大数据实战——MapReduce案例实践 一.过程分析(截图)1. 确定Hadoop处于启动状态2. 在/usr/local/filecotent…...

OpenCV基础(3)
1.图像直方图 1.1.像素统计 计算图像均值: Scalar cv::mean(InputArray src,InputArray masknoArray()); src:输入图像mask:掩膜层过滤 返回值是对输入图像通道数计算均值后的Scalar对象 计算图像均值与方差: void cv::meanSt…...

大语言模型---RewardBench 介绍;RewardBench 的主要功能;适用场景
文章目录 1. RewardBench 介绍2. RewardBench 的主要功能3. 适用场景 1. RewardBench 介绍 RewardBench: Evaluating Reward Models是一个专门用于评估 Reward Models(奖励模型) 的公开平台,旨在衡量模型在多种任务上的性能,包括…...

泷羽sec-linux
基础之linux 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团…...

栈、队列、链表
一、栈 1. 定义 栈是一种线性数据结构,遵循后进先出(LIFO, Last In First Out)的原则。这意味着最后被添加到栈中的元素将会是最先被移除的元素。 2. 基本操作 Push:将一个元素添加到栈顶。Pop:移除并返回栈顶的元…...

【maven】配置下载私有仓库的快照版本
1、setting.xml配置 <settings xmlns"http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/SETTINGS/1.0.0https://maven.apache.org/xsd/settings-1.0.0.…...

LabVIEW引用类型转换问题
一、问题描述 在LabVIEW中,refnum(引用编号)用于引用各种资源,如文件、队列、控件等。这些引用是与具体类型相关的,通常情况下,LabVIEW会根据引用的类型自动进行处理。然而,当不同类型的引用需…...

GUI智能代理:用AI代理玩米哈游游戏《崩坏》
项目名称:The Dawn of GUI Agent研究对象:Claude 3.5 Computer Use特点:首个公测版GUI智能代理系统 技术创新 首创性:这是首个提供公测版图形界面控制功能的前沿AI模型。交互方式:实现了从自然语言到桌面操作的端到端控制,用户可以通过简单的自然语言指令完成复杂的桌面…...

系统思考—环路图的好处
每次内部学习,我们都会用系统环路图拆解那些动态性复杂的议题。这不仅仅是我们教学的工具,更是我们在实践中不断应用和打磨的利器。 我常在课程中和大家分享,什么原因要持续使用系统环路图? 🎯 1. 落地全局思维 环路图…...

torch.set_printoptions
torch.set_printoptions 设置pytorch打印张量时的选项,比如限制打印的元素数量、设置精度等。在打印大张量或者需要更精确控制输出格式时非常有用。 torch.set_printoptions(precisionNone, thresholdNone, edgeitemsNone, linewidthNone, profileNone, sci_modeN…...

Nexus搭建go私有仓库,加速下载go依赖包
一、搭建go私库 本文我们梳理一下go依赖包的私库搭建以及使用。 它只分为proxy和group两种仓库,这一点和maven仓库有所不同。 1、创建Blob Stores 为了区分不同的私库依赖包,存储的位置分隔开。 2、新建go proxy官网 Remote storage:htt…...

Qt6 Android设置文件读写权限设置
一.概述 1.在Qt中设置Android应用程序的文件读写权限,你需要在Android的Manifest文件中声明所需的权限。对于文件读写,通常需要声明以下权限: android.permission.READ_EXTERNAL_STORAGE:允许应用程序从外部存储读取数据。 android.permission.WRITE_EXTERNAL_STORAGE:允…...

TCP快速重传机制为啥出现重复ACK?
TCP快速重传机制为啥出现重复ACK 简单来说,丢失数据包后发送方至少发了三个请求,每个请求返回接收方下一次期待的序列号ACK,也就是丢失数据包之前的一个正常请求的确认ACK值 在 TCP(Transmission Control Protocol,传…...

SSM--SpringMVC复习(二)
请求 URL匹配: RequestMapping RequestMapping 负责将请求映射到对应的控制器方法上。 RequestMapping 注解可用于类或方法上。用于类上,表示类中的所有响应请求的方法都以该地址作为父路径。 在整个 Web 项目中,RequestMapping 映射的请求…...

C语言蓝桥杯组题目
系列文章目录 文章目录 系列文章目录前言题目第一题.1, 2, 3, 4 能组成多少个互不相同且无重复数字的三位数?都是多少?思路 第二题: 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少…...