一、栈的案例
1. 进制转换
- 十进制整数 N 向其他进制数 d (二、八、十六)的转换是计算机实现计算的基本问题。换成什么进制的数就%什么进制。
转换法则:除以 d 倒取余
- 该转换法则对应一个简单算法原理:n = (n div d) * d + n mod d。
- 其中:div 为整除运算,mod 为求余运算。
举个例子:把十进制数 159 转换成 八进制数
-
先用159 / 8,商19余7,然后用19 / 8,商2余3,最后用2 / 8,商0余2,把得到的余数倒着取回来,就是八进制数237了。
-
所以就可以用栈来实现这样一个结果,每次都将得到的余数进栈,当商为0的时候就说明操作结束了,然后再让求完的余数依次出栈,进制转换结果就出来了。
2. 括号匹配的检验
- 假设表达式中允许包含两种括号:圆括号和方括号;
- 其嵌套的顺序随意,即:
- 这些括号只能嵌套不能交叉,括号数量也要正确,不能少括号。依然可以使用栈来检验是否匹配。+
举个例子
- 先入栈的括号后匹配,后入栈的扩号先匹配。
- 将第三个准备进栈的右括号先和栈顶的左括号看看能不能匹配上,如果能匹配上就将栈顶的左括号出栈。
- 接下来的是个方括号 ] ,看看和栈顶的圆左括号是否匹配,匹配不了就说明这一整个嵌套的括号是不匹配的。
算法步骤
- 可以利用一个栈结构保存每个出现的左括号,当遇到右括号时,从栈中弹出左括号,检验匹配情况。
- 在检验过程中,若遇到以下几种情形之一,就可以得出括号不匹配的结论。
- 当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号。
- 从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉的情况。
- 算术表达式输入完毕,但是栈中还有没有匹配的左括号,说明左括号多于右括号。
3. 表达式求值
- 表达式求值是程序设计语言编译中一个最基本的问题,它的实现也需要运用栈。
- 这里介绍的算法是由运算符优先级确定运算顺序的对表达式求值算法——算符优先算法。
表达式的组成
- 操作数:常数、变量。
- 运算符:算术运算符,关系运算符和逻辑运算法。
- 界限符:左右括弧和表达式结束符。
算术表达式
- 任何一个算术表达式都由操作数(常数、变量)、算术运算符(+、- 、* 、/)和界限符(括号、表达式结束符 ‘#’ 、 虚设的表达式起始符 ‘#’ )组成。后两者统称为算符。
- 例如:# 3 *(7 - 2) #
为了实现表达式求值,需要设置两个栈:
- 一个是算符栈 OPTR,用于寄存运算符。
- 另一个称为操作栈数 OPND,用于寄存运算数和运算结果。
求值过程
- 求值的处理过程是自左至右扫描表达式的每一个字符。
- 当扫描到的是运算数,则将其压入栈 OPND,
- 当扫描到的是运算符时:
- 若这个运算符比 OPTR 栈顶运算符的优先级高,则入栈 OPTR,继续向后处理。
- 若这个运算符比 OPTR 栈顶运算符优先级低,则从 OPND 栈中弹出两个运算数,从栈 OPTR 中弹出栈顶运算符进行运算,并将运算结果压入栈 OPND。
- 继续处理当前字符,直到遇到结束符为止。
二、队列案例
1. 舞伴问题
问题描述:假设在舞会上,男士和女士各自排成一队。舞会开始时,依次从男队和女队的队头各出一人配成舞伴。如果两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲,现要求写一算法模拟上述舞伴配对问题。
解题思路:显然,先入队的男士或女士先出队配成舞伴。因此该问题具有典型的先进先出特性,可以用队列作为算法的数据结构。
- 首先构造两个队列(QM存男性,QF存女性);
- 依次从队头元素出队配成舞伴;
- 当某队为空,则另一队的等待者则是下一个舞曲第一个可获得舞伴的人。