说说你对栈、队列的理解?应用场景?
一、栈
栈(stack)又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表
表尾这一端被称为栈顶,相反地另一端被称为栈底,向栈顶插入元素被称为进栈、入栈、压栈,从栈顶删除元素又称作出栈
所以其按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据,具有记忆作用
关于栈的简单实现,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | class Stack { constructor() { this .items = []; } /** * 添加一个(或几个)新元素到栈顶 * @param {*} element 新元素 */ push(element) { this .items.push(element) } /** * 移除栈顶的元素,同时返回被移除的元素 */ pop() { return this .items.pop() } /** * 返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它) */ peek() { return this .items[ this .items.length - 1] } /** * 如果栈里没有任何元素就返回true,否则返回false */ isEmpty() { return this .items.length === 0 } /** * 移除栈里的所有元素 */ clear() { this .items = [] } /** * 返回栈里的元素个数。这个方法和数组的length属性很类似 */ size() { return this .items.length } } |
关于栈的操作主要的方法如下:
- push:入栈操作
- pop:出栈操作
二、队列
跟栈十分相似,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作
进行插入操作的端称为队尾,进行删除操作的端称为队头,当队列中没有元素时,称为空队列
在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出
简单实现一个队列的方式,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Queue { constructor() { this .list = [] this .frontIndex = 0 this .tailIndex = 0 } enqueue(item) { this .list[ this .tailIndex++] = item } unqueue() { const item = this .list[ this .frontIndex] this .frontIndex++ return item } } |
上述这种入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用
当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作,出该现象称为"假溢"
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:
无论插入或删除,一旦rear
指针增1或front
指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置,这种队列也就是循环队列
下面实现一个循环队列,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Queue { constructor(size) { this .size = size; // 长度需要限制, 来达到空间的利用, 代表空间的长度 this .list = []; this .font = 0; // 指向首元素 this .rear = 0; // 指向准备插入元素的位置 } enQueue() { if ( this .isFull() == true ) { return false } this .rear = this .rear % this .k; this ._data[ this .rear++] = value; return true } deQueue() { if ( this .isEmpty()){ return false ; } this .font++; this .font = this .font % this .k; return true ; } isEmpty() { return this .font == this .rear - 1; } isFull() { return this .rear % this .k == this .font; } } |
上述通过求余的形式代表首尾指针增1 时超出了所分配的队列空间
三、应用场景
栈
借助栈的先进后出的特性,可以简单实现一个逆序数处的功能,首先把所有元素依次入栈,然后把所有元素出栈并输出
包括编译器的在对输入的语法进行分析的时候,例如"()"
、"{}"
、"[]"
这些成对出现的符号,借助栈的特性,凡是遇到括号的前半部分,即把这个元素入栈,凡是遇到括号的后半部分就比对栈顶元素是否该元素相匹配,如果匹配,则前半部分出栈,否则就是匹配出错
包括函数调用和递归的时候,每调用一个函数,底层都会进行入栈操作,出栈则返回函数的返回值
生活中的例子,可以把乒乓球盒比喻成一个堆栈,球一个一个放进去(入栈),最先放进去的要等其后面的全部拿出来后才能出来(出栈),这种就是典型的先进后出模型
队列
当我们需要按照一定的顺序来处理数据,而该数据的数据量在不断地变化的时候,则需要队列来帮助解题
队列的使用广泛应用在广度优先搜索种,例如层次遍历一个二叉树的节点值(后续将到)
生活中的例子,排队买票,排在队头的永远先处理,后面的必须等到前面的全部处理完毕再进行处理,这也是典型的先进先出模型
参考文献
- https://baike.baidu.com/item/%E6%A0%88/12808149
- https://baike.baidu.com/item/%E9%98%9F%E5%88%97/14580481
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
2023-04-11 记录-css实现交融文字效果