先进后出,后进先出,这就是典型的栈结构。


栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。这种限制相较于数组和链表这样的线性表来说,操作更加可控安全不易出错。

因此当某个数据集合只涉及在一端插入删除,且满足先进后出、后进先出特性时,首选“栈”这种数据结构。

栈的实现

栈可以用数组或者链表实现(数组:顺序栈;链表:链式栈)

以数组为例:

一种基本的栈类的实现:1. 内部保存一个数组;2.仅给外界暴露的入栈和出栈的方法(实现先进后出、后进先出)。 数组如果是OC中NSMutableArray可以支持动态扩容。

如果按之前的数组扩容时的操做(重新申请更大的空间,将原本数据复制过去)来计算入栈时间复杂度:最好情况O(1),最坏O(n)。均摊复杂度O(1)。



栈在函数调用中的应用

操做系统给每个线程分配了一块独立的内存空间,这块内存空间被阻止成“栈”的结构,用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈。当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。



栈在表达式求值中的应用

编译器如何利用栈来实现表达式求值:通过两个栈来实现。其中一个保存操作数,另一个保存运算符。从左向右遍历表达式,遇到数组直接压入数字栈;遇到运算符,就与运算符栈顶元素进行比较。

如果>顶元素优先级,入栈;相反<=,取出栈顶运算符,再从操作数栈栈顶取2个操作数计算的结果压入操作数栈中,继续比较。



栈在括号匹配中的应用

[{}{()}]检查包含括号的表达式是否合法。遇到左括号入栈,遇到右括号栈顶出栈和它比较,相等则继续;否则不合法。

栈在浏览器中的应用

实现浏览器前进后退功能:两个栈分别存储之前的页面和之后的页面。