热门标签 | 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;数组的最小偏移量

推荐阅读
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
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社区 版权所有