当前位置: 首页 > news >正文

【数据结构】双向链表、单向循环链表、双向循环链表、栈、链栈

目录

一、双向链表

定义类和封装函数以及测试样例如下:

注意事项:

二、循环链表

单循环列表的类和函数封装如下:

注意事项: 

三、双向循环链表

结点类和双循环链表的定义部分

函数封装之判空和尾插

双循环链表遍历

双循环链表尾删

完整测试以及结果:

四、栈

顺序栈

顺序栈本质以及组成

顺序栈的操作

链栈


一、双向链表

对于单向链表而言。只能通过头节点或者第一个节点出发,单向的访问后继节点,每个节点只能记录其后继节点的信息(位置),不能向前遍历。

所以引入双向链表,双向链表可以保持单向链表特点的基础上,让每个节点,既能向后访问后继节点,也可以向前访问前驱节点。

相较于单向链表,我们更多的是在每个结点上加入了一个前驱链接域

定义类和封装函数以及测试样例如下:

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

未完待续(持续跟新中)🏆

相关文章:

【数据结构】双向链表、单向循环链表、双向循环链表、栈、链栈

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

(动画)Qt控件 QProgressBar

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

【AI】基础原理

文章目录 前言1. AI 是如何学习的&#xff1f;2. AI 怎么做决定&#xff1f;3. AI 的“大脑”是什么样的&#xff1f;4. AI 为什么会犯错&#xff1f;5. AI 的不同类型总结&#xff1a;AI 的本质是什么&#xff1f; 前言 人工智能&#xff08;AI&#xff09;这个词对很多人来说…...

多模态大型语言模型(MLLM)综述

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

计算机的错误计算(一百六十六)

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

typeof 和 as 关键字

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

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提交到远程仓库如何撤回? 要撤回已经提交到远程仓库的更改&#xff0c;你可以使用以下步骤&#xff1a; 首先&#xff0c;确保你的本地仓库是最新状态。如果不是&#xff0c;请先执行 git pull 来更新你的本地仓库。 使用 git log 查看提交历史&#xff0c;找到你想要撤回…...

微信小程序常用全局配置项及窗口组成部分详解

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

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 是一个开源的物联网平台&#xff0c;提供了设备…...

「Mac玩转仓颉内测版32」基础篇12 - Cangjie中的变量操作与类型管理

本篇将深入探讨 Cangjie 编程语言中的变量操作与类型管理&#xff0c;涵盖变量的定义、作用域、类型推断、常量、变量遮蔽、类型转换等方面的知识。通过这些概念的学习&#xff0c;开发者将更好地理解和灵活掌握变量的使用与管理技巧。 关键词 变量定义类型推断常量变量作用域…...

【Android】RecyclerView回收复用机制

概述 RecyclerView 是 Android 中用于高效显示大量数据的视图组件&#xff0c;它是 ListView 的升级版本&#xff0c;支持更灵活的布局和功能。 我们创建一个RecyclerView的Adapter&#xff1a; public class MyRecyclerView extends RecyclerView.Adapter<MyRecyclerVie…...

麒麟系统性能瓶颈分析

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

Java二分查找+冒泡排序

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

(三)手势识别——动作识别应用【代码+数据集+python环境(免安装)+GUI系统】

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

大数据实战——MapReduce案例实践

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

OpenCV基础(3)

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

大语言模型---RewardBench 介绍;RewardBench 的主要功能;适用场景

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

泷羽sec-linux

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

栈、队列、链表

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

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...