栈的应用

当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。

在函数调用中的应用

操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。

每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

为什么函数调用要用“栈”来保存临时变量呢?用其他数据结构不行吗?

不一定非要用栈来保存临时变量,只不过如果这个函数调用符合后进先出的特性,用栈这种数据结构来实现,是最顺理成章的选择。

从调用函数进入被调用函数,对于数据来说,变化的是什么呢?是作用域。所以根本上,只要能保证每进入一个新的函数,都是一个新的作用域就可以。而要实现这个,用栈就非常方便。在进入被调用函数的时候,分配一段栈空间给这个函数的变量,在函数结束的时候,将栈顶复位,正好回到调用函数的作用域内。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在表达式求值中的应用

例如 34+13*9+44-12/3,

对于这个四则运算,我们人脑可以很快求解出答案,但是对于计算机来说,理解这个表达式本身就是个挺难的事。

实现这样一个表达式求值,实际上编译器就是通过两个栈来实现的。

其中一个保存操作数的栈,另一个是保存运算符的栈。

从左到右遍历表达式,当遇到操作数,就直接压入操作数栈, 当遇到数字,我们就直接压入操作数栈;

当遇到运算符,就与运算符栈的栈顶元素进行比较。

如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;

如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取 2 个操作数,然后进行计算

再把计算完的结果压入操作数栈,继续比较。

例如,3+5*8-6

 

在括号匹配中的应用

假设表达式中只包含三种括号,圆括号 ()、方括号[]和花括号{},并且它们可以任意嵌套。

比如,{[] ()[{}]}或[{()}([])]等都为合法格式,而{[}()]或[({)]为不合法的格式。

如何检查它是否合法,可以用栈来解决。我们用栈来保存未匹配的左括号,从左到右依次扫描字符串。

当扫描到左括号时,则将其压入栈中;当扫描到右括号时,从栈顶取出一个左括号。

如果能够匹配,则继续扫描剩下的字符串。

如果扫描的过程中,遇到不能配对的右括号,或者栈中没有数据,则说明为非法格式。

当所有的括号都扫描完成之后,如果栈为空,则说明字符串为合法格式;

否则,说明有未匹配的左括号,为非法格式。

 

栈的API

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章