数据结构与算法--栈、队列篇
一、计算机领域的地位
在计算机科学的广袤领域中,数据结构犹如一座精巧的大厦,为信息的存储和处理提供了坚实的框架。而在众多的数据结构中,栈和队列宛如两颗璀璨的明珠,各自闪耀着独特的光芒。
栈和队列虽然看似简单,却蕴含着深刻的逻辑和强大的功能。它们是解决众多复杂问题的基石,从程序的执行流程控制到各种算法的优化,从操作系统的任务调度到网络通信中的数据传输,栈和队列都发挥着不可或缺的作用。
深入理解栈和队列,不仅能够提升我们对数据组织和操作的认知,更能为我们在编程和算法设计中打开新的思路,使我们能够更加高效、优雅地解决实际问题。在接下来的篇章中,让我们一同走进栈和队列的精彩世界,探索它们的奥秘与魅力。
二、栈(Stack)的详解
栈是一种特殊的线性表,其操作遵循“后进先出(Last In First Out,LIFO)”的原则。
一、栈的定义
栈只允许在一端进行插入(入栈)和删除(出栈)操作,这一端被称为栈顶,而另一端则被称为栈底。
二、栈的基本操作
-
入栈(Push):将元素添加到栈顶。
- 例如,一个初始为空的栈,依次入栈元素 10、20、30 ,此时栈顶元素为 30 。
-
出栈(Pop):删除栈顶元素。
- 对于上述栈,执行出栈操作,先弹出的是 30 。
-
读取栈顶元素(Peek):获取栈顶元素的值,但不删除它。
-
判空(IsEmpty):判断栈是否为空。
三、栈的实现方式
-
顺序栈:使用数组来实现。
- 优点:操作简单,随机访问速度快。
- 缺点:需要预先分配固定大小的空间,可能造成空间浪费或溢出。
下面是用python实现的顺序栈结构:
# 顺序栈实现
class SequentialStack:def __init__(self, size=10):"""初始化顺序栈参数:size (int): 栈的初始大小"""self.stack = [None] * size # 存储栈元素的列表self.top = -1 # 栈顶指针def is_empty(self):"""判断栈是否为空返回:bool: 如果栈为空返回 True,否则返回 False"""return self.top == -1def is_full(self):"""判断栈是否已满返回:bool: 如果栈已满返回 True,否则返回 False"""return self.top == len(self.stack) - 1def push(self, element):"""向栈中压入元素参数:element: 要压入栈的元素异常:Exception: 如果栈已满,抛出"Stack Overflow"异常"""if self.is_full():raise Exception("Stack Overflow")self.top += 1self.stack[self.top] = elementdef pop(self):"""从栈中弹出元素返回:弹出的元素异常:Exception: 如果栈为空,抛出"Stack Underflow"异常"""if self.is_empty():raise Exception("Stack Underflow")element = self.stack[self.top]self.stack[self.top] = Noneself.top -= 1return elementdef peek(self):"""查看栈顶元素但不弹出返回:栈顶元素异常:Exception: 如果栈为空,抛出"Stack is empty"异常"""if self.is_empty():raise Exception("Stack is empty")return self.stack[self.top]
2. 链式栈:使用链表来实现。
- 优点:灵活,不受固定空间限制。
- 缺点:访问节点需要遍历,效率相对较低。
下面是用python实现的链式栈结构:
# 链式栈节点
class Node:def __init__(self, data=None):"""初始化链式栈节点参数:data: 节点存储的数据,默认为 None"""self.data = dataself.next = None# 链式栈实现
class LinkedStack:def __init__(self):"""初始化链式栈"""self.top = None # 栈顶节点def is_empty(self):"""判断链式栈是否为空返回:bool: 如果为空返回 True,否则返回 False"""return self.top is Nonedef push(self, element):"""向链式栈中压入元素参数:element: 要压入的元素"""new_node = Node(element) # 创建新节点new_node.next = self.top # 新节点指向当前栈顶self.top = new_node # 更新栈顶def pop(self):"""从链式栈中弹出元素返回:弹出的元素异常:Exception: 如果栈为空,抛出"Stack Underflow"异常"""if self.is_empty():raise Exception("Stack Underflow")element = self.top.data # 获取栈顶节点数据self.top = self.top.next # 更新栈顶return elementdef peek(self):"""查看链式栈栈顶元素但不弹出返回:栈顶元素异常:Exception: 如果栈为空,抛出"Stack is empty"异常"""if self.is_empty():raise Exception("Stack is empty")return self.top.data
四、栈的应用场景
-
函数调用:函数的调用和返回可以通过栈来管理。
- 当一个函数被调用时,相关的参数、局部变量等信息被压入栈中;函数返回时,这些信息从栈中弹出。
-
表达式求值:如中缀表达式转后缀表达式,然后进行计算。
-
括号匹配:检查表达式中的括号是否正确匹配。
-
回溯算法:在搜索过程中保存当前状态,以便回溯。
总之,栈虽然结构简单,但在计算机科学的众多领域中发挥着重要作用,是理解和解决许多复杂问题的基础工具。
三、队列(Queue)的详解
一、队列的定义
队列只允许在一端进行插入操作(称为队尾,Rear),在另一端进行删除操作(称为队头,Front)。
二、队列的基本操作
-
入队(Enqueue):将元素添加到队尾。
- 例如,一个初始为空的队列,依次入队元素 5、15、25 ,此时队头元素为 5 。
-
出队(Dequeue):删除队头元素。
- 对于上述队列,执行出队操作,先弹出的是 5 。
-
读取队头元素(Front):获取队头元素的值,但不删除它。
-
判空(IsEmpty):判断队列是否为空。
-
判满(IsFull):对于有固定大小的队列,判断是否已满。
三、队列的实现方式
-
顺序队列:使用数组来实现。
- 可能会出现“假溢出”的情况,即队列未满但无法再插入元素。
- 为解决此问题,可采用循环队列的方式。
以下是用python代码实现的顺序队列:
class SequentialQueue:def __init__(self, size=10):self.queue = [None] * sizeself.front = 0self.rear = 0def is_empty(self):return self.front == self.reardef is_full(self):return (self.rear + 1) % len(self.queue) == self.frontdef enqueue(self, element):if self.is_full():raise Exception("Queue Overflow")self.queue[self.rear] = elementself.rear = (self.rear + 1) % len(self.queue)def dequeue(self):if self.is_empty():raise Exception("Queue Underflow")element = self.queue[self.front]self.queue[self.front] = Noneself.front = (self.front + 1) % len(self.queue)return elementdef get_front(self):if self.is_empty():raise Exception("Queue is empty")return self.queue[self.front]
创建一个队列对象即可使用。
-
链式队列:使用链表来实现。
以下是用python实现的链式队列:
class Node:def __init__(self, data=None):self.data = dataself.next = Noneclass Queue:def __init__(self):self.front = Noneself.rear = Nonedef enqueue(self, data):new_node = Node(data)if not self.rear:self.front = new_nodeself.rear = new_nodeelse:self.rear.next = new_nodeself.rear = new_nodedef dequeue(self):if not self.front:return "Queue is empty"temp = self.frontif self.front == self.rear:self.front = Noneself.rear = Noneelse:self.front = self.front.nextreturn temp.datadef is_empty(self):return self.front is Nonedef print_queue(self):current = self.frontwhile current:print(current.data, end=" ")current = current.nextprint()# 测试队列
q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
q.print_queue()
print(q.dequeue())
q.print_queue()
经测试,得出链式队列具有较强的稳定性。
四、队列的应用场景
-
任务调度:操作系统按照任务进入队列的先后顺序进行调度。
-
消息队列:在分布式系统中用于消息的传递和处理。
-
广度优先搜索:在图的遍历中使用队列来保存待访问的节点。
总之,队列以其独特的先进先出特性,在计算机科学和实际应用中发挥着重要作用,为数据的有序处理提供了有效的手段。
四、BFS(广度优先搜索)和队列的关系:
BFS 通常使用队列来实现。在 BFS 中,我们先访问起始节点,然后将其相邻节点放入队列。接着依次取出队列头部的节点,并将其未访问过的相邻节点放入队列。这个过程一直持续,直到队列为空。
例如,对于一个简单的二叉树:
class TreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = None# 构建二叉树
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)def bfs(root):queue = [root]while queue:current = queue.pop(0)print(current.value)if current.left:queue.append(current.left)if current.right:queue.append(current.right)bfs(root)
五、DFS(深度优先搜索)和栈的关系:
DFS 通常使用栈来实现。在 DFS 中,我们先访问起始节点,然后将其相邻节点压入栈。接着取出栈顶节点,并将其未访问过的相邻节点压入栈。这个过程一直持续,直到栈为空。
以下是一个使用栈实现 DFS 的示例:
def dfs(root):stack = [root]while stack:current = stack.pop()print(current.value)if current.right:stack.append(current.right)if current.left:stack.append(current.left)dfs(root)
总结:
队列是先进先出的数据结构,适合 BFS 逐层扩展搜索。栈是先进后出的数据结构,适合 DFS 深入一条路径后再回溯。通过这些数据结构的特性,能够有效地实现不同的搜索策略。
例如,在图的遍历中,如果要尽快找到距离起始节点较近的所有节点,通常使用 BFS;而如果要探索整个图的所有可能路径或者找到一条到达目标节点的最长路径,可能会使用 DFS。
“且将新火试新茶,诗酒趁年华”——《望江南·超然台作》
相关文章:
数据结构与算法--栈、队列篇
一、计算机领域的地位 在计算机科学的广袤领域中,数据结构犹如一座精巧的大厦,为信息的存储和处理提供了坚实的框架。而在众多的数据结构中,栈和队列宛如两颗璀璨的明珠,各自闪耀着独特的光芒。 栈和队列虽然看似简单&…...
【程序、游戏、人生】致敬飞逝的3年和新的开始
人,总要向前看。 感谢之前关注的朋友,感谢各位朋友的私信、感谢关心的评论。 不要停下 20年:某银行业务三方开发。 21年:移动内部业务平台开发移动物联网商城开发储备TPL。 22年-至今:手游发行技术综合北漂 经历了行…...
第三届人工智能、人机交互与机器人国际会议
国际人工智能、人机交互和机器人会议是一项年度活动,汇集了来自世界各地的研究人员、从业者和行业专业人士,分享他们在人工智能、人际交互和机器人领域的知识和专业知识。在过去的几十年里,这些领域在计算能力、数据分析和机器学习技术的进步…...

AWS生成式AI项目的全生命周期管理
随着人工智能技术的迅速发展,生成式 AI 已成为当今最具创新性和影响力的领域之一。生成式 AI 能够创建新的内容,如文本、图像、音频等,具有广泛的应用前景,如自然语言处理、计算机视觉、创意设计等。然而,构建一个成功…...
windows go grpc
windows环境安装go grpc 的工具和插件 在Windows环境下,安装Protocol Buffers(proto)和gRPC相关的工具和插件,可以通过以下几个步骤进行 1.安装protoc 在git 仓库下载tag 包 https://github.com/protocolbuffers/protobuf/rele…...

Leetcode 第 135 场双周赛题解
Leetcode 第 135 场双周赛题解 Leetcode 第 135 场双周赛题解题目1:3222. 求出硬币游戏的赢家思路代码复杂度分析 题目2:3223. 操作后字符串的最短长度思路代码复杂度分析 题目3:3224. 使差值相等的最少数组改动次数思路代码复杂度分析 题目4…...
rpc的原理
RPC(Remote Procedure Call,远程过程调用)是一种编程模型,它允许开发者像调用本地函数一样调用位于不同进程或者不同机器上的函数或服务。这种抽象简化了分布式系统的开发,使得开发人员无需关注底层网络通信细节&#…...

【无线通信发展史-第二篇】,带你走进查利·奥古斯丁·库仑的世界,了解(库伦定律)-(扭秤实验)-(如何测量出静电力常量)
前言:用这几个问答形式来解读下我这个系列的来龙去脉。如果大家觉得本篇文章不水的话希望帮忙点赞收藏加关注,你们的鼓舞是我继续更新的动力。 我为什么会写这个系列呢? 首先肯定是因为我本身就是一名从业通信者,想着更加了解自…...

CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法2)
在文章CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法1)中,我们声明一个结构体DoIPMessage表示完整的DoIP车辆声明消息: 上半部分是DoIP报头通用部分(也就是所有类型的DoIP消息都有的),而payload是每个类型的DoIP消息独有的部分,对于车辆声明消息来说,用另一个结…...
基于Matlab的车牌识别系统设计与实现
基于Matlab的车牌识别系统设计与实现 摘要 随着智能交通系统的不断演进,车牌识别技术已成为提升交通管理效率与准确性的关键。本文深入探讨了基于Matlab平台的车牌识别系统设计与实现,该系统通过精细的图像预处理、高效的车牌定位算法、精准的字符分割…...

使用Cisco进行模拟RIP路由协议配置
实验四 RIP路由协议配置 文章目录 实验四 RIP路由协议配置1.实验目的2.实验流程3.RIPv1实验步骤4.RIPv2实验步骤 1.实验目的 1)理解RIP路由的原理 2)掌握RIP路由的配置方法 2.实验流程 开始→布置拓扑→配置IP地址→配置并验证RIPv1→配置并验证RIPv2…...

段页式存储-系统架构师(三十七)
1、一个完整的系统需要从不同的角度进行描述,下图属于软件架构设计中的(),用于()视图来描述软件系统。 问题1 A对象图 B时序图 C构件图 D类图 问题2 A进程 B开发 C物理 D逻辑 解析: 从…...

通过指令深入了解Linux
文章目录 1.简单介绍XShell1.1下载安装XShell1.2 使用XShell登录主机1.3 XShell下的复制粘贴 2. Linux下的基本指令2.1 ls指令2.1.1 对文件的理解2.1.2 目录下的隐藏文件 2.2 pwd指令2.3 cd指令2.3.1 Linux下目录结构的认识 2.4 touch指令2.5 mkdir指令2.6 clear指令 1.简单介绍…...

IP探针双端源码
源码耗费两年半的制作过程 将源码上传至你的服务器或你的主机 可以对接其他东西或者网站其他语言 使用方法 1.参数使用 http://域名/sc.php?id这是生成端 http://域名/sc1.php?id这是生成端生成的链接可以跳转链接 http://域名/ck.php?id这是查看IP 生成端,生成完…...

高中数学学科知识与教学能力
梳理...

Flink 实时数仓(七)【DWS 层搭建(一)流量域汇总表创建】
前言 今天开始 DWS 层的搭建,不知不觉又是周一,都忘了昨天是周末,近两年对我来说,周六日晚上八九点能打一小会篮球就算一周的休息了。不得不说自己真的是天生打工体质,每天不管多累,晚上十二点睡࿰…...

Python和PyCharm的安装激活及Python新手入门指南
一、软件介绍 Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。于 1989 年底由 Guido van Rossum 发明,第一个公开发行版发行于 1991 年。 当然也有很多小伙伴不清楚python与pycharm的区别和联系,接下来给大家简单介绍一下࿱…...
Apache Flink窗口机制解析:滚动窗口与滑动窗口的比较与应用
Apache Flink是一个开源的流处理框架,用于实现大规模数据流的处理和分析。在处理数据流时,窗口操作是一种常见的方法,它允许对数据流中连续的项目进行分组。Flink提供了多种窗口类型,其中滚动窗口(Tumbling Window&…...

为什么《程序员修炼之道》评分能到 9.1?
大家好,我是 方圆。开始接触到《程序员修炼之道:通向务实的最高境界》这本书是在豆瓣图书的高分榜单上,它的评分高达 9.1,其中有条蛮有意思的书评非常吸引我:“这本书我读过 5 遍信不信,每个字都磨出了感情…...
接口自动化测试框架中动态参数接口,加密接口,签名接口你们是怎么处理的?
动态参数:可通过热加载形式(在代码执行过中自动去yaml里面执行外部的函数) 接口测试加密解密简介: 对称加密(私钥加密,只有一个密钥)AES,DES,BASE64 特点是:加密和解密有相同的密钥…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...