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

数据结构与算法--栈、队列篇

一、计算机领域的地位        

        在计算机科学的广袤领域中,数据结构犹如一座精巧的大厦,为信息的存储和处理提供了坚实的框架。而在众多的数据结构中,栈和队列宛如两颗璀璨的明珠,各自闪耀着独特的光芒。

        栈和队列虽然看似简单,却蕴含着深刻的逻辑和强大的功能。它们是解决众多复杂问题的基石,从程序的执行流程控制到各种算法的优化,从操作系统的任务调度到网络通信中的数据传输,栈和队列都发挥着不可或缺的作用。

        深入理解栈和队列,不仅能够提升我们对数据组织和操作的认知,更能为我们在编程和算法设计中打开新的思路,使我们能够更加高效、优雅地解决实际问题。在接下来的篇章中,让我们一同走进栈和队列的精彩世界,探索它们的奥秘与魅力。


二、栈(Stack)的详解

栈是一种特殊的线性表,其操作遵循“后进先出(Last In First Out,LIFO)”的原则。

一、栈的定义

        栈只允许在一端进行插入(入栈)和删除(出栈)操作,这一端被称为栈顶,而另一端则被称为栈底。

二、栈的基本操作

  1. 入栈(Push):将元素添加到栈顶。

    • 例如,一个初始为空的栈,依次入栈元素 10、20、30 ,此时栈顶元素为 30 。
  2. 出栈(Pop):删除栈顶元素。

    • 对于上述栈,执行出栈操作,先弹出的是 30 。
  3. 读取栈顶元素(Peek):获取栈顶元素的值,但不删除它。

  4. 判空(IsEmpty):判断栈是否为空。

三、栈的实现方式

  1. 顺序栈:使用数组来实现。

  • 优点:操作简单,随机访问速度快。
  • 缺点:需要预先分配固定大小的空间,可能造成空间浪费或溢出。

下面是用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

四、栈的应用场景

  1. 函数调用:函数的调用和返回可以通过栈来管理。

  • 当一个函数被调用时,相关的参数、局部变量等信息被压入栈中;函数返回时,这些信息从栈中弹出。
  1. 表达式求值:如中缀表达式转后缀表达式,然后进行计算。

  2. 括号匹配:检查表达式中的括号是否正确匹配。

  3. 回溯算法:在搜索过程中保存当前状态,以便回溯。

        总之,栈虽然结构简单,但在计算机科学的众多领域中发挥着重要作用,是理解和解决许多复杂问题的基础工具。


三、队列(Queue)的详解

一、队列的定义

        队列只允许在一端进行插入操作(称为队尾,Rear),在另一端进行删除操作(称为队头,Front)。

二、队列的基本操作

  1. 入队(Enqueue):将元素添加到队尾。

    • 例如,一个初始为空的队列,依次入队元素 5、15、25 ,此时队头元素为 5 。
  2. 出队(Dequeue):删除队头元素。

    • 对于上述队列,执行出队操作,先弹出的是 5 。
  3. 读取队头元素(Front):获取队头元素的值,但不删除它。

  4. 判空(IsEmpty):判断队列是否为空。

  5. 判满(IsFull):对于有固定大小的队列,判断是否已满。

三、队列的实现方式

  1. 顺序队列:使用数组来实现。

    • 可能会出现“假溢出”的情况,即队列未满但无法再插入元素。
    • 为解决此问题,可采用循环队列的方式。

以下是用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]

        创建一个队列对象即可使用。

  1. 链式队列:使用链表来实现。

以下是用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()  

经测试,得出链式队列具有较强的稳定性。 

四、队列的应用场景

  1. 任务调度:操作系统按照任务进入队列的先后顺序进行调度。

  2. 消息队列:在分布式系统中用于消息的传递和处理。

  3. 广度优先搜索:在图的遍历中使用队列来保存待访问的节点。

        总之,队列以其独特的先进先出特性,在计算机科学和实际应用中发挥着重要作用,为数据的有序处理提供了有效的手段。


四、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 层的搭建,不知不觉又是周一,都忘了昨天是周末,近两年对我来说,周六日晚上八九点能打一小会篮球就算一周的休息了。不得不说自己真的是天生打工体质,每天不管多累,晚上十二点睡&#xff0…...

Python和PyCharm的安装激活及Python新手入门指南

一、软件介绍 Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。于 1989 年底由 Guido van Rossum 发明,第一个公开发行版发行于 1991 年。 当然也有很多小伙伴不清楚python与pycharm的区别和联系,接下来给大家简单介绍一下&#xff1…...

Apache Flink窗口机制解析:滚动窗口与滑动窗口的比较与应用

Apache Flink是一个开源的流处理框架,用于实现大规模数据流的处理和分析。在处理数据流时,窗口操作是一种常见的方法,它允许对数据流中连续的项目进行分组。Flink提供了多种窗口类型,其中滚动窗口(Tumbling Window&…...

为什么《程序员修炼之道》评分能到 9.1?

大家好,我是 方圆。开始接触到《程序员修炼之道:通向务实的最高境界》这本书是在豆瓣图书的高分榜单上,它的评分高达 9.1,其中有条蛮有意思的书评非常吸引我:“这本书我读过 5 遍信不信,每个字都磨出了感情…...

接口自动化测试框架中动态参数接口,加密接口,签名接口你们是怎么处理的?

动态参数:可通过热加载形式(在代码执行过中自动去yaml里面执行外部的函数) 接口测试加密解密简介: 对称加密(私钥加密,只有一个密钥)AES,DES,BASE64 特点是:加密和解密有相同的密钥…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...