【数据结构与算法】之栈 vs 队列

栈和队列是计算机科学中最基础也是最常用的两种线性数据结构,它们提供了一种组织和管理数据的方式。它们的主要区别在于元素的添加和删除顺序。理解它们的特点、差异以及底层实现对于选择合适的结构解决特定问题至关重要。本文将更详细地比较栈和队列,并提供Java示例代码进行演示。

1. 栈 (Stack)

栈遵循后进先出 (LIFO - Last-In, First-Out) 的原则。想象一下一堆盘子,你总是从顶部添加或拿走盘子,最后放上去的盘子最先被拿走。

1.1 特点

  • LIFO: 这是栈的核心特性,也是其应用场景的决定性因素。

  • 单端操作: 所有的操作(添加、删除、查看)都只在栈顶进行,这使得栈的操作非常简单高效。

  • 主要操作:

    • push(element): 将元素添加到栈顶。如果栈已满,则抛出异常(对于固定大小的栈)或动态扩展栈的大小(对于动态大小的栈)。

    • pop(): 移除并返回栈顶元素。如果栈为空,则抛出异常。

    • peek(): 返回栈顶元素但不移除。如果栈为空,则抛出异常。

    • isEmpty(): 检查栈是否为空。

  • 实现方式:

    • 数组: 可以使用数组实现栈,使用一个变量top来指向栈顶元素的索引。push操作将元素添加到top位置,然后top加1;pop操作返回top位置的元素,然后top减1。

    • 链表: 可以使用链表实现栈,将栈顶元素作为链表的头节点。push操作将新元素插入到链表头部;pop操作删除链表头部节点。链表实现的栈可以动态调整大小,避免了数组实现的栈可能出现的溢出问题。

  • 应用场景:

    • 函数调用栈: 存储函数调用信息,包括局部变量、参数、返回地址等。这使得函数的嵌套和递归调用成为可能。

    • 表达式求值: 例如,使用栈将中缀表达式转换为后缀表达式,然后进行求值。

    • 撤销操作 (Undo/Redo): 在文本编辑器、绘图软件等应用中,使用栈存储用户的操作历史,实现撤销和重做功能。

    • 浏览器历史记录: 后退按钮模拟了栈的操作,每次点击后退按钮就返回上一个访问的页面。

    • 深度优先搜索 (DFS): 图算法中使用栈来实现深度优先搜索。

1.2 Java示例 (数组实现)

import java.util.Stack;public class StackExample {public static void main(String[] args) {Stack<Integer> stack = new Stack<>();stack.push(1);stack.push(2);stack.push(3);System.out.println("栈顶元素: " + stack.peek()); // 输出 3System.out.println("弹出栈顶元素: " + stack.pop()); // 输出 3System.out.println("栈是否为空: " + stack.isEmpty()); // 输出 falsewhile (!stack.isEmpty()) {System.out.println(stack.pop()); // 输出 2, 1}}
}

2. 队列 (Queue)

队列遵循先进先出 (FIFO - First-In, First-Out) 的原则。就像排队一样,先来的人先得到服务。

2.1 特点

  • FIFO: 队列的核心特性,决定了它的应用场景。

  • 双端操作: 元素从队尾(rear)添加,从队首(front)删除。

  • 主要操作:

    • enqueue(element) 或 offer(element): 将元素添加到队尾。offer() 在队列满时不会抛出异常,而是返回false。

    • dequeue() 或 poll(): 移除并返回队首元素。poll() 在队列为空时不会抛出异常,而是返回null。

    • peek() 或 element(): 返回队首元素但不移除。peek() 在队列为空时返回null,element() 抛出异常。

    • isEmpty(): 检查队列是否为空。

  • 实现方式:

    • 数组: 使用循环数组实现队列,需要维护队首front和队尾rear两个指针。enqueue操作将元素添加到rear位置,dequeue操作返回front位置的元素。

    • 链表: 使用链表实现队列,队首作为链表的头节点,队尾作为链表的尾节点。enqueue操作将新元素添加到链表尾部,dequeue操作删除链表头部节点。

  • 应用场景:

    • 进程调度: 操作系统使用队列管理等待执行的进程,确保先到达的进程先被执行。

    • 打印队列: 管理待打印文档的顺序,确保先提交的文档先被打印。

    • 缓冲区: 例如,网络缓冲区用于临时存储数据包,确保数据包按照到达的顺序被处理。

    • 广度优先搜索 (BFS): 图算法中使用队列实现广度优先搜索。

    • 生产者-消费者模型: 队列可以作为生产者和消费者之间传递数据的缓冲区.

2.2 Java示例 (链表实现)

import java.util.LinkedList;
import java.util.Queue;public class QueueExample {public static void main(String[] args) {Queue<String> queue = new LinkedList<>();queue.offer("A");queue.offer("B");queue.offer("C");System.out.println("队首元素: " + queue.peek()); // 输出 ASystem.out.println("移除队首元素: " + queue.poll()); // 输出 ASystem.out.println("队列是否为空: " + queue.isEmpty()); // 输出 falsewhile (!queue.isEmpty()) {System.out.println(queue.poll()); // 输出 B, C}}
}

3. 栈与队列的比较

特性队列
原理LIFO (后进先出)FIFO (先进先出)
数据访问只允许访问栈顶元素只允许访问队首和队尾元素
添加元素push()enqueue() / offer()
删除元素pop()dequeue() / poll()
查看元素peek()peek() / element()
主要应用函数调用、表达式求值、撤销操作、DFS进程调度、打印队列、缓冲区、BFS、生产者-消费者模型
空间复杂度O(n)O(n)
时间复杂度 (push/pop/enqueue/dequeue/peek)O(1)O(1) (使用链表实现) / O(n) (在数组实现中,某些情况下需要移动元素)

4. 选择合适的结构

选择栈还是队列取决于具体的应用场景。如果需要按照最后添加的元素先处理的顺序,则应该使用栈;如果需要按照先添加的元素先处理的顺序,则应该使用队列. 分析问题的核心需求,例如数据处理的顺序,才能做出最佳选择.

5. 总结

栈和队列是两种简单但功能强大的数据结构,理解它们的工作原理、实现方式以及应用场景对于编写高效的程序至关重要。 通过选择正确的数据结构,可以简化代码逻辑并提高程序性能。 希望本文更详细的比较和Java示例能够帮助你更好地理解和应用栈和队列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/56586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java多线程详解①(全程干货!!!)

这里是Themberfue 今天&#xff0c;我们将正式进入多线程章节的讲解&#xff0c;希望我的讲解能够让你理解&#x1f60e; 进程 在进入多线程的讲解中&#xff0c;我们先引入进程的概念及其解释 操作系统都是大家耳熟能详的名词&#xff0c;常见的操作系统主要有&#xff1a;Li…

opencv - py_ml - py_knn k-最近邻算法

文章目录 1.理解 k-最近邻算法目标理论OpenCV 中的 kNN其他资源 2.使用 kNN 对手写数据进行 OCR目标手写数字的 OCR英文字母的 OCR其他资源 1.理解 k-最近邻算法 目标 在本章中&#xff0c;我们将理解 k-最近邻算法 (kNN) 的概念。 理论 kNN 是监督学习中最简单的分类算法之…

从0到1学习node.js(path模块以及HTTP协议)

文章目录 一、path模块二、HTTP协议1、常见状态码分类2、IP地址3、端口 一、path模块 // 引入path模块 const path require(path)// 拼接地址 const resolveData path.resolve(__dirname, ./index) console.log(__dirname, __dirname) console.log(resolveData, resolveData…

【js逆向专题】12.RPC技术

目录 一. websocket1. 什么是websocket2. websocket的原理3. websocket实现方式1. 客户端2.服务端3. 实际案例1. 案例目标2. 解析思路 二. RPC1. RPC 简介2.Sekiro-RPC1. 使用方法1. 执行方式2.客户端环境3.使用参数说明 2. 测试使用1. 前端代码2. SK API3.python调用代码 三.项…

C++,STL 042(24.10.21)

内容 一道练习题。 &#xff08;涉及list&#xff0c;sort&#xff09; 题目&#xff08;大致&#xff09; 将Person自定义类型进行排序&#xff08;Person中属性有姓名、年龄、身高&#xff09;&#xff0c;按照年龄进行升序&#xff0c;如果年龄相同则按照身高进行降序。 …

openpnp - 解决“底部相机高级校正成功后, 开机归零时,吸嘴自动校验失败的问题“

文章目录 openpnp - 解决"底部相机高级校正成功后, 开机归零时&#xff0c;吸嘴自动校验失败的问题"概述笔记问题现象1问题现象2原因分析现在底部相机和吸嘴的位置偏差记录修正底部相机位置现在再看看NT1在底部相机中的位置开机归零&#xff0c;看看是否能通过所有校…

【分布式微服务云原生】《Redis 分布式锁的挑战与解决方案及 RedLock 的强大魅力》

《Redis 分布式锁的挑战与解决方案及 RedLock 的强大魅力》 摘要&#xff1a; 本文深入探讨了使用 Redis 做分布式锁时可能遇到的各种问题&#xff0c;并详细阐述了相应的解决方案。同时&#xff0c;深入剖析了 RedLock 作为分布式锁的原因及原理&#xff0c;包括其多节点部署…

HarmonyOS鸿蒙- 一行代码自动换行技巧

DevEco Studio 编辑器设置 一行代码自动换行显示。 一、代码自动换行设置方式路径&#xff1a;File > Editor > General 如图: 二、找到标题&#xff1a;Soft Wraps 勾选《Soft-wrap these files:》&#xff0c;然后在后面添加*.ets 然后保存即可。添加后&#xff0c…

【TIMM库】是一个专门为PyTorch用户设计的图像模型库 python库

TIMM库 1、引言&#xff1a;遇见TIMM2、初识TIMM&#xff1a;安装与基本结构3、实战案例一&#xff1a;图像分类4、实战案例二&#xff1a;迁移学习5、实战案例三&#xff1a;模型可视化6、结语&#xff1a;TIMM的无限可能 1、引言&#xff1a;遇见TIMM 大家好&#xff0c;我是…

LangSplat和3D language fields简略介绍

LangSplat: 3D Language Gaussian Splatting 相关技术拆分解释&#xff1a; 3dgs&#xff1a;伟大无需多言SAM&#xff1a;The Segment Anything Model&#xff0c;是图像分割领域的foundational model&#xff0c;已经用在很多视觉任务上&#xff08;如图像修复、物体追踪、图…

支持国密算法的数字证书-国密SSL证书详解

在互联网中&#xff0c;数字证书作为标志通讯各方身份信息的数字认证而存在&#xff0c;常见的数字证书大都采用国际算法&#xff0c;比如RSA算法、ECC算法、SHA2算法等。随着我国加强网络安全技术自主可控的大趋势&#xff0c;也出现了支持国密算法的数字证书-国密SSL证书。那…

OpenCV高级图形用户界面(21)暂停程序执行并等待用户按键输入函数waitKey()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 等待按键 该函数 waitKey 在 delay≤0 时无限等待按键事件&#xff0c;或者在 delay 为正数时等待 delay 毫秒。由于操作系统在切换线程时有最小…

一文详解视频参数——FFmpeg -i选项下的视频参数解析

随着多媒体内容在网络上的日益普及,对视频文件的处理需求也变得越来越重要。FFmpeg 是一款强大的跨平台音视频编解码库及工具集,能够帮助开发者实现对音频、视频文件的转码、剪辑、合并等多种功能。本文将重点探讨如何利用 ffmpeg -i xxx.mp4 来获取视频文件的基本信息,并对…

前端工程启动工具

一些思考 在公司项目中&#xff0c;需要启一个新的前端工程&#xff08;一个基于Webpack的React工程&#xff09;。因为同一个项目中有其他的前端工程&#xff0c;我们最开始想的是参考另外一个工程的配置重启一个新的工程&#xff0c;但是又因为原来的工程用的库版本都比较老…

软件设计师:软件工程

文章目录 一、开发模型&#xff08;1&#xff09;瀑布模型&#xff08;需求明确&#xff09;&#xff08;2&#xff09;增量模型&#xff08;快速构建&#xff09;&#xff08;3&#xff09;演化模型&#xff08;迭代模型&#xff09;&#xff08;3.1&#xff09;原型模型&…

自学C语言——函数(全)

接上一篇&#xff1a;自学C语言——数组&#xff08;二&#xff09; 1.函数的概念 C语言中&#xff1a;函数子程序 C语言中的函数就是一个完成某项特定的任务的一小段代码。 2.库函数 标准库和头文件 C语言标准中规定了C语言的语法规则&#xff0c;C语言不提供库函数&am…

Ubuntu 22.04上安装Miniconda

在Ubuntu 22.04上安装Miniconda&#xff0c;可以按照以下步骤进行&#xff1a; 步骤1&#xff1a;更新系统 首先&#xff0c;更新您的系统软件包&#xff1a; sudo apt update sudo apt upgrade -y步骤2&#xff1a;下载Miniconda安装脚本 访问Miniconda的官方网站或使用以下…

IAR全面支持旗芯微车规级MCU,打造智能安全的未来汽车

中国上海&#xff0c;2024年10月18日 — 在全球汽车电子快速发展的今天&#xff0c;IAR与苏州旗芯微半导体有限公司&#xff08;以下简称“旗芯微”&#xff09;联合宣布了一项激动人心的合作——IAR Embedded Workbench for Arm 9.60.2版本现已全面支持旗芯微车规级MCU&#x…

【Docker】docker | 部署nginx

一、概述 记录下nginx的部署流程&#xff1b;将conf配置文件映射到宿主机 前提依赖&#xff1a;自行准备nginx的镜像包 二、步骤 1、运行、无映射 docker run --name nginx -p 80:80 -d nginx:1.18.0-alpine 80&#xff1a;80&#xff0c;前面是宿主机端口&#xff1b;如果冲…

IPsec简单介绍

VPN相关介绍 VPN&#xff1a;虚拟私有网络 例如&#xff1a;像这种不加密的 PPTPL2TP ------- 一般用在windows server 服务端&#xff08;但是大多数企业不用这个&#xff09; 假如总公司内部的PC1要去访问分公司内部的PC2&#xff08;一般用在公司服务器有内网的服务&#…