03《数据结构入门教程》栈和队列

1. 前言

栈和队列是 Java 数据结构中比较简单但又非常重要的类型,我们需要了解栈和队列的存储原理以及各自的特点,熟悉他们各自的常用操作。

2. 后进先出

周末陪孩子玩新买的玩具枪,看到弹夹我乐了,这不就是一个栈容器吗!儿子问我什么是栈,我反问儿子,你装弹的顺序和子弹打出去的顺序有没有关联或规律呢?儿子想了一会说,最先装进去的子弹要等到最后才能被发射出去,而第一发子弹是最后一个装进去的! [图片上传失败...(image-29af7-1658654574813)]

(图片来源于网络,版权归原作者所有)

正像枪的弹夹一样,栈表示的是一个后进先出的对象,也叫堆栈。无需百度,直接打开 java.util.Stack 源码还能看到 Java 为此定义了一个专属单词 LIFO ,其实就是 last-in-first-out 的缩写。 细心的小伙伴还会从源码中发现 Stack 其实是继承自 Vector ,上一节我们介绍了数组, Vector 就是可实现自动增长的对象数组,它支持线程的同步。所以我们可以发现,栈的本质也是数组。数据从栈顶压入,操作的时候先从栈顶取出。

3. 栈的常用操作

5f026a14097f900008710686.jpg

创建一个栈只需要 new Stack () 来在内存中开辟一块连续的默认容量为 10 的空间。添加元素我们称之为压入 push () , 取出元素我们使用 pop () , 查看栈顶元素我们可以使用 peek () , 此外我们还可以使用 empty () 来判断当前栈是否为空栈。

<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n14" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">//声明一个栈对象,并向内压入三个元素
Stack stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
//判断是否为空栈
System.out.println(stack.isEmpty());//输出:false
//使用peek()方法查询栈顶元素,使用pop()方法取出栈顶元素
System.out.println(stack.peek());//输出:3
System.out.println(stack.pop());//输出:3
System.out.println(stack.peek());//输出:2
System.out.println(stack.pop());//输出:2
System.out.println(stack.peek());//输出:1
System.out.println(stack.pop());//输出:1
System.out.println(stack.isEmpty());//输出:true
代码块123456789101112131415</pre>

5ee860d80a92e09812000900.jpg

堆栈类非常简单,但请不要忽视父类 Vector 中有很多方法,感兴趣的小伙伴可以去看源码,后面我们也会介绍 Vector。
5ee860f00938b32c09330887.jpg

4. 队列的定义和特点

我们还是从源码中去寻找队列的官方定义,跟栈一样简单的一句话:order elements in a FIFO (first-in-first-out) manner. 翻译成中文就是 “先来后到”。数据从队列的一端进入,从另一端取出。先到先得在我们生活中最常见的例子就是排队了。

5. 队列的常用操作

队列的常用操作也非常简单,我们可以看源码中对 Queue 类中六个方法的介绍。

  • add () :增加一个元素,如果队列已满,则抛出一个 IIIegaISlabEepeplian 异常;

  • remove () :移除并返回队列头部的元素,如果队列为空,则抛出一个 NoSuchElementException 异常;

  • element () :返回队列头部的元素,如果队列为空,则抛出一个 NoSuchElementException 异常;

  • offer () :添加一个元素并返回 true,如果队列已满,则返回 false;

  • poll () :返问并移除队列头部的元素,如果队列为空,则返回 null;

  • peek () :返回队列头部的元素,如果队列为空,则返回 null;

<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n35" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">//声明一个队列
Queue queue = new LinkedList();
//先向队列中添加五个元素
queue.add(1);
queue.add(2);
queue.add(3);
queue.add(4);
queue.add(5);
//移除并返回队列头部的元素
System.out.println(queue.remove());//输出:1
//返回队列头部的元素
System.out.println(queue.element());//输出:2
//添加一个元素并返回true,如果队列已满则返回false
System.out.println(queue.offer(6));//输出:true
//返回队列头部的元素
System.out.println(queue.peek());//输出:2
//返问并移除队列头部的元素
System.out.println(queue.poll());//输出:2
System.out.println(queue.poll());//输出:3
System.out.println(queue.poll());//输出:4
System.out.println(queue.poll());//输出:5
System.out.println(queue.poll());//输出:6
代码块12345678910111213141516171819202122</pre>

但是我们创建 Queue 的时候会发现直接实例化会报错,因为它是 interface 接口,实例化的时候可以用 LinkedList,LinkedList 继承自 Deque,Deque 继承自 Queue。

5f02697a09b1f55f08940249.jpg

6. 栈和队列的对比

通过这一节的学习我们知道了栈和队列都是线性表,区别在于栈限定只能在表的一端(栈顶)进行插入和删除操作,队列限定只能在表的一端进行插入,在另一端进行删除

5ee8616b0a2a51bc12000675.jpg

7. 栈和队列的应用场景

栈和队列在我们自己的开发工作中使用是相对比较少的,但是对它们的实际应用却随处可见:

  • 我们的开发工具会对括号 “(” 关闭进行匹配校验,就是在输入左括号 “(” 时将其压入栈内,在输入右括号 “)” 时从栈中取出并进行匹配校验

  • 我们在进行一系列操作后想要撤回上一步操作,也是从我们的操作记录栈中取出了之前操作的历史记录

  • 关于迷宫的解法也用到了栈,用于在使用 “穷举解法” 时记录前面的尝试记录

  • 队列因为可以完美模拟排队场景,因此在餐厅叫号程序、银行医院的排队系统中都会用到队列结构。

8. 小结

通过学习我们知道了栈和队列都是线性数据结构,栈的特点是后进先出,常用的操作有压入 push ()、查询 peek () 和取出 pop () 等;队列的特点是先进先出,常用的操作有添加 add ()、查询 element () 和 peek ()、从队列头部取出 poll () 以及移除 remove () 等。我们要熟练掌握常用的操作和方法,结合实际应用场景,充分利用好它们各自的特点。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容