栈的两个典型应用
最开始先来介绍一下栈的定义:
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出
(Last in First out)的线性表,简称LIFO结构。
栈的插入操作叫做进栈(push),类似子弹入弹夹;删除操作叫做出栈(pop),类似子弹出弹夹。
和大多数数据结构一样,栈也分成顺序存储结构和链式存储结构。
栈的典型应用一:递归
所谓递归即是指直接调用自己或者通过一系列操作间接调用自己。
对于递归函数,最重要的是要有合适的退出条件,否则可能就会陷入永不结束的无穷递归中,那么程序就飞啦~
递归能让程序结构更加清晰和简介,可读性更高,但是大量的递归调用会占用大量的运行时间和内存,使用过程
中要合理利用递归。
说了这么多,那么递归和栈又有什么联系呢?
递归过程在不断的调用自身函数之后,当到达退出条件后会,会按照它前行顺序的逆序执行退回。在前行阶段,
对于每一层递归,函数的局部变量、参数值和返回地址被压入栈中。在退回阶段,位于栈顶的局部变量、参数值
和返回地址被弹出,用于返回调用层次中执行代码的其余部分。
这些需求很符合栈的数据结构,所以现在的编译器大多通过栈来实现递归操作。
栈的典型应用二:四则运算表达式求值
使用C语言来实现对同时存在括号和四则运算符的表达式求值一直是个难题,直到逻辑学家们借助栈和后缀表达法
才解决这一难题。
后缀表达法(又名逆波兰表达式),叫后缀的原因是所有的符号都要在运算符号的后面出现。
那么由我们常用的数学表达式(中缀表达式)转换为后缀表达式的规则是什么?
从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;
若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)
则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
举个例子:表达式
9+(3-1)*3+10/2
对应的后缀表达式为
9 3 1 - 3*+10 2 / +
而计算机针对后缀表达式的运算规则为:从左到右遍历表达式的每个数字和符号,遇到是数字
就进栈,遇到是符号,就将栈顶的两个数字出栈,进行运算,运算结果进栈,一直到得到最终
结果。不难得出上述后缀表达式的值为:
20