热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

栈和队列的概念

文章目录栈、队列和双端队列栈队列双端队列Java中的栈、队列和双端队列单调栈和单调队列二叉堆和优先队列二叉堆优先队列目录栈、队列和双端队列栈和队列是常见的数据结构。栈的特点是后进


文章目录

  • 栈、队列和双端队列
    • 队列
    • 双端队列
    • Java 中的栈、队列和双端队列
  • 单调栈和单调队列
  • 二叉堆和优先队列
    • 二叉堆
    • 优先队列
  • 目录


栈、队列和双端队列

栈和队列是常见的数据结构。栈的特点是后进先出,添加元素、删除元素和查看元素都在栈顶操作。队列的特点是先进先出,添加元素在队尾操作,删除元素和查看元素在队首操作。

双端队列比栈和队列更加灵活,可以在双端队列的两端添加元素、删除元素和查看元素。

栈、队列和双端队列都满足每次添加元素、删除元素和查看元素的时间复杂度是 O(1)O(1)O(1)

栈、队列和双端队列都可以基于数组或链表实现。


栈是一种特殊的线性表,特点是后进先出,最先加入的元素最后取出,最后加入的元素最先取出。

栈的常见操作包括判断栈是否为空和获得栈内元素个数,以及对元素的操作。对元素的操作都位于栈顶,包括以下三种操作:


  • 添加元素:将元素加入栈顶,该操作称为入栈;
  • 删除元素:将栈顶元素删除,该操作称为出栈;
  • 查看元素:获得栈顶元素,不删除元素。

下图为栈的示意,左边为栈底,右边为栈顶。将数字 111555 依次入栈之后,栈的状态如下图所示,此时栈顶元素是 555,第一个出栈的元素是 555

图 1


队列

队列是一种特殊的线性表,特点是先进先出,最先加入的元素最先取出,最后加入的元素最后取出。队列有头部和尾部,队列头部称为队首,队列尾部称为队尾,队列内的元素从队首到队尾的顺序符合加入队列的顺序。

队列的常见操作包括判断队列是否为空和获得队列内元素个数,以及对元素的操作。对元素的操作包括以下三种操作:


  • 添加元素:将元素加入队尾,该操作称为入队;
  • 删除元素:将队首元素删除,该操作称为出队;
  • 查看元素:获得队首元素,不删除元素。

需要注意的是,队列的三种对元素的操作所在的位置不同,查看元素和删除元素位于队首,添加元素位于队尾。

下图为队列的示意,左边为队首,右边为队尾。将数字 111555 依次入队之后,队列的状态如下图所示,此时队首元素是 111,队尾元素是 555,第一个出队的元素是 111

图 2


双端队列

双端队列是一种特殊的线性表,同时具有栈和队列的性质,特点是在队首和队尾都可以加入和取出元素。栈和队列都可以基于双端队列实现。


Java 中的栈、队列和双端队列

Java 提供了多种类和接口支持栈、队列和双端队列的实现。

Stack\texttt{Stack}Stack 类是早期版本的栈的实现类,继承自 Vector\texttt{Vector}Vector 类。在后续版本中,JDK 的官方文档不建议使用 Stack\texttt{Stack}Stack 类实现栈的功能,而是建议使用 Deque\texttt{Deque}Deque 接口及其实现类实现栈的功能。

Queue\texttt{Queue}Queue 接口是队列的接口,需要通过实现类完成实例化,常见的实现类包括 ArrayDeque\texttt{ArrayDeque}ArrayDeque 类和 LinkedList\texttt{LinkedList}LinkedList 类。

Deque\texttt{Deque}Deque 接口是双端队列的接口,需要通过实现类完成实例化,常见的实现类包括 ArrayDeque\texttt{ArrayDeque}ArrayDeque 类和 LinkedList\texttt{LinkedList}LinkedList 类。

ArrayDeque\texttt{ArrayDeque}ArrayDeque 类和 LinkedList\texttt{LinkedList}LinkedList 类都可以作为栈和队列的实现类,区别在于,ArrayDeque\texttt{ArrayDeque}ArrayDeque 类的底层实现是循环数组,LinkedList\texttt{LinkedList}LinkedList 类的底层实现是双向链表。根据 JDK 的官方文档,ArrayDeque\texttt{ArrayDeque}ArrayDeque 类作为栈使用时效率高于 Stack\texttt{Stack}Stack 类,ArrayDeque\texttt{ArrayDeque}ArrayDeque 类作为队列使用时效率高于 LinkedList\texttt{LinkedList}LinkedList 类。无论是栈的实现还是队列的实现,都推荐使用 ArrayDeque\texttt{ArrayDeque}ArrayDeque 类。


单调栈和单调队列

单调栈和单调队列是栈和队列的高级应用,可以解决一些复杂的问题。

单调栈和单调队列满足元素的单调性。具体而言,单调栈内从栈底到栈顶的元素依次递增或递减,单调队列内从队首到队尾的元素依次递增或递减。在单调栈和单调队列中添加元素时,必须维护元素的单调性。

向单调栈添加元素时,首先需要检查栈顶元素和待添加元素是否满足单调性,如果不满足单调性则将栈顶元素出栈,直到栈为空或者栈顶元素和待添加元素满足单调性,然后将待添加元素入栈。

向单调队列添加元素时,首先需要检查队尾元素和待添加元素是否满足单调性,如果不满足单调性则将队尾元素出队,直到队列为空或者队尾元素和待添加元素满足单调性,然后将待添加元素入队。

由于普通的队列不支持在队尾将元素出队,因此需要使用双端队列实现单调队列的功能。

单调栈和单调队列的应用需要考虑具体情况。有时需要维护下标信息,因此在单调栈和单调队列中存储的不是元素本身,而是元素下标,下标对应的元素满足单调性。

使用单调栈和单调队列实现通常需要两层循环,但是由于每个元素最多只会在单调栈或单调队列中被添加一次和删除一次,因此时间复杂度是线性复杂度,而不是平方复杂度。


二叉堆和优先队列

优先队列是一种不同于栈、队列和双端队列的数据结构。栈、队列和双端队列的实现原理是线性表,而优先队列的实现原理是二叉堆。


二叉堆

在介绍二叉堆之前,首先需要介绍二叉树和完全二叉树。

二叉树是一个树的结构,每个结点最多有两个子结点,称为左子结点和右子结点。

完全二叉树的性质是&#xff0c;除了层数最大的层以外&#xff0c;其余各层的结点数都达到最大值&#xff0c;且层数最大的层的所有结点都连续集中在最左边。假设完全二叉树有 lll 层&#xff0c;其中根结点位于第 000 层&#xff0c;则对于 0≤i0i<l1&#xff0c;第 iii 层有 2i2^i2i 个结点。

二叉堆是一棵完全二叉树&#xff0c;其中的元素按照特定规则排列。常见的例子有小根堆和大根堆。


  • 小根堆的性质是&#xff0c;每个结点的值都小于其子结点的值&#xff0c;根结点的值是堆中最小的&#xff1b;
  • 大根堆的性质是&#xff0c;每个结点的值都大于其子结点的值&#xff0c;根结点的值是堆中最大的。

在二叉堆中添加元素和删除元素时&#xff0c;必须维护二叉堆的性质。以小根堆为例&#xff0c;添加元素和删除元素的操作如下&#xff1a;


  • 添加元素时&#xff0c;假设添加的元素是 xxx&#xff0c;首先将 xxx 添加到末尾&#xff0c;然后比较 xxx 和父结点元素的大小&#xff0c;如果 xxx 小于父结点元素&#xff0c;则将 xxx 和父结点交换&#xff0c;直到 xxx 到达根结点或者大于等于父结点元素&#xff1b;
  • 删除元素时&#xff0c;假设堆中的最后一个元素是 xxx&#xff0c;首先将 xxx 放置到根结点处&#xff0c;然后比较 xxx 和子结点元素的大小&#xff0c;如果 xxx 大于至少一个子结点元素&#xff0c;则将 xxx 和较小的子结点交换&#xff0c;直到 xxx 到达叶结点&#xff08;没有子结点&#xff09;或者小于等于全部子结点元素。

考虑以下小根堆。

图 3

888 添加到小根堆中&#xff0c;首先将 888 添加到末尾。

图 4

由于 888 比父结点 151515 小&#xff0c;因此交换&#xff0c;交换后 888 比父结点 101010 小&#xff0c;因此再次交换&#xff0c;此时 888 不再比父结点 555 小&#xff0c;因此停止交换。添加元素操作结束。

图 5

在添加 888 之后&#xff0c;删除元素。删除堆顶元素 555&#xff0c;将最后一个元素 151515 放置到根结点处。

图 6

由于 151515 比两个子结点元素都大&#xff0c;因此和较小的子结点 888 交换&#xff0c;交换后 151515 比较小的子结点 101010 大&#xff0c;因此和较小的子结点 101010 交换&#xff0c;此时 151515 不再比子结点 303030 大&#xff0c;因此停止交换。删除元素操作结束。

图 7

假设二叉堆中的元素个数是 nnn&#xff0c;二叉堆的层数是 lll。根据上述例子可知&#xff0c;在二叉堆中添加元素和删除元素时&#xff0c;需要维护二叉堆的性质&#xff0c;时间复杂度是 O(l)O(l)O(l)&#xff0c;由于 O(l)&#61;O(log⁡n)O(l) &#61; O(\log n)O(l)&#61;O(logn)&#xff0c;因此二叉堆的添加元素和删除元素的时间复杂度是 O(log⁡n)O(\log n)O(logn)


优先队列

不同于栈的后进先出和队列的先进先出&#xff0c;优先队列中的每个元素都有优先级&#xff0c;优先级最高的元素位于队首&#xff0c;也是最先取出的元素。

Java 的 PriorityQueue\texttt{PriorityQueue}PriorityQueue 类是优先队列类&#xff0c;继承自 AbstractQueue\texttt{AbstractQueue}AbstractQueue 抽象类。PriorityQueue\texttt{PriorityQueue}PriorityQueue 类的实现原理是二叉堆&#xff0c;底层实现是数组&#xff0c;二叉堆满足堆顶元素为优先级最高的元素。创建优先队列的时候可以自定义优先队列中的元素的比较方法&#xff0c;从而自定义优先级。

由于 Java 的优先队列的实现原理是二叉堆&#xff0c;因此优先队列的添加元素和删除元素的时间复杂度是 O(log⁡n)O(\log n)O(logn)&#xff0c;查看元素的时间复杂度是 O(1)O(1)O(1)&#xff0c;其中 nnn 是优先队列中的元素个数。


目录


  1. 栈题目&#xff1a;文件夹操作日志搜集器
  2. 栈题目&#xff1a;括号的最大嵌套深度
  3. 栈题目&#xff1a;有效的括号
  4. 栈题目&#xff1a;棒球比赛
  5. 栈题目&#xff1a;删除最外层的括号
  6. 栈题目&#xff1a;删除字符串中的所有相邻重复项
  7. 栈题目&#xff1a;用栈操作构建数组
  8. 栈题目&#xff1a;两数相加 II
  9. 栈题目&#xff1a;逆波兰表达式求值
  10. 栈题目&#xff1a;使括号有效的最少添加
  11. 栈题目&#xff1a;平衡括号字符串的最少插入次数
  12. 栈题目&#xff1a;最小栈
  13. 栈题目&#xff1a;行星碰撞
  14. 栈题目&#xff1a;验证栈序列
  15. 栈题目&#xff1a;检查替换后的词是否有效
  16. 栈题目&#xff1a;反转每对括号间的子串
  17. 栈题目&#xff1a;移除无效的括号
  18. 栈题目&#xff1a;简化路径
  19. 栈题目&#xff1a;括号的分数
  20. 栈题目&#xff1a;函数的独占时间
  21. 栈题目&#xff1a;字符串解码
  22. 栈题目&#xff1a;解析布尔表达式
  23. 栈题目&#xff1a;有效括号的嵌套深度
  24. 栈题目&#xff1a;删除字符串中的所有相邻重复项 II
  25. 栈题目&#xff1a;迷你语法分析器
  26. 栈题目&#xff1a;设计浏览器历史记录
  27. 栈题目&#xff1a;基本计算器
  28. 栈题目&#xff1a;基本计算器 II
  29. 栈题目&#xff1a;文件的最长绝对路径
  30. 栈题目&#xff1a;标签验证器
  31. 队列题目&#xff1a;无法吃午餐的学生数量
  32. 队列题目&#xff1a;最近的请求次数
  33. 队列题目&#xff1a;用队列实现栈
  34. 队列题目&#xff1a;用栈实现队列
  35. 队列题目&#xff1a;按递增顺序显示卡牌
  36. 队列题目&#xff1a;设计循环队列
  37. 队列题目&#xff1a;设计循环双端队列
  38. 单调栈题目&#xff1a;去除重复字母
  39. 单调栈题目&#xff1a;移掉 K 位数字
  40. 单调栈题目&#xff1a;找出最具竞争力的子序列
  41. 单调栈题目&#xff1a;132 模式
  42. 单调栈题目&#xff1a;每日温度
  43. 单调栈题目&#xff1a;接雨水
  44. 单调栈题目&#xff1a;股票价格跨度
  45. 单调栈题目&#xff1a;最大宽度坡
  46. 单调栈题目&#xff1a;子数组的最小值之和
  47. 单调栈题目&#xff1a;柱状图中最大的矩形
  48. 单调栈题目&#xff1a;最大矩形
  49. 单调队列题目&#xff1a;绝对差不超过限制的最长连续子数组
  50. 单调队列题目&#xff1a;满足不等式的最大值
  51. 单调队列题目&#xff1a;和至少为 K 的最短子数组
  52. 优先队列题目&#xff1a;最后一块石头的重量
  53. 优先队列题目&#xff1a;数据流中的第 K 大元素
  54. 优先队列题目&#xff1a;拼车
  55. 优先队列题目&#xff1a;合并K个升序链表
  56. 优先队列题目&#xff1a;滑动窗口最大值
  57. 优先队列题目&#xff1a;数据流的中位数
  58. 优先队列题目&#xff1a;多次求和构造目标数组
  59. 优先队列题目&#xff1a;数组的最小偏移量

推荐阅读
  • 设计实战 | 10个Kotlin项目深度解析:首页模块开发详解
    设计实战 | 10个Kotlin项目深度解析:首页模块开发详解 ... [详细]
  • CAS 机制下的无锁队列设计与实现 ... [详细]
  • 深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用
    深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • Spring Boot 应用中实现观察者模式的深度解析与实践
    在 Spring Boot 应用中,观察者模式是一种常用的设计模式,用于建立对象间的依赖关系。当某一对象的状态发生改变时,所有依赖该对象的对象会自动接收到通知并进行相应的更新。本文将深入探讨观察者模式的实现原理,并通过具体实例展示如何在 Spring Boot 项目中有效应用这一模式,以提高系统的解耦性和可维护性。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
  • 本文总结了JavaScript的核心知识点和实用技巧,涵盖了变量声明、DOM操作、事件处理等重要方面。例如,通过`event.srcElement`获取触发事件的元素,并使用`alert`显示其HTML结构;利用`innerText`和`innerHTML`属性分别设置和获取文本内容及HTML内容。此外,还介绍了如何在表单中动态生成和操作``元素,以便更好地处理用户输入。这些技巧对于提升前端开发效率和代码质量具有重要意义。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • Spring框架的核心组件与架构解析 ... [详细]
  • 本课程深入探讨了 Python 中自定义序列类的实现方法,涵盖从基础概念到高级技巧的全面解析。通过实例演示,学员将掌握如何创建支持切片操作的自定义序列对象,并了解 `bisect` 模块在序列处理中的应用。适合希望提升 Python 编程技能的中高级开发者。 ... [详细]
  • 在Python多进程编程中,`multiprocessing`模块是不可或缺的工具。本文详细探讨了该模块在多进程管理中的核心原理,并通过实际代码示例进行了深入分析。文章不仅总结了常见的多进程编程技巧,还提供了解决常见问题的实用方法,帮助读者更好地理解和应用多进程编程技术。 ... [详细]
  • 如何使用 com.jme3.input.FlyByCamera 构造函数及其代码示例详解 ... [详细]
author-avatar
mobiledu2502931637
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有