栈和队列的应用相关习题及详解 ——数据结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22073849/article/details/78416135

习题部分

选择题

第一题

一个问题的递归算法求解和其相对应的非递归算法求解()
A. 递归算法通常高效一些 B. 非递归算法通常高效一些
C. 两者相同 D. 无法比较

第二题

执行()操作时,需要使用队列作为辅助存储空间
A. 查找散列(哈希)表 B. 广度优先搜索图
C. 前序(根)遍历二叉树 D. 深度优先搜索图

第三题

已知操作符包括‘+’‘-’‘’‘/’‘(’‘)’ 。将中缀表达式a+b-a((c+d)/e-f)+g转化为等价的后缀表达式ab+acd+e/f-*-g+时,用栈来存放暂时还不能确定运算次序的操作符。若栈初始时为空,则转换过程中同事保存在栈中的操作符的最大个数是()

A. 5 B. 7
C. 8 D. 11

第四题

假设栈初始为空,将中缀表达式a/b+(c*d-e*f)/g转化为等价的狗追表达式的过程中,当扫描到f时,栈中的元素依次是()

A. +(*- B. +(-* C. /+(*-* D. /+-*


解答部分

第一题

通常情况下,递归算法在计算机实际执行的过程中包含很多的重复计算,所以效率会低

第二题

图的广度优先搜索类似于树的层序遍历,同样需要借助于队列

第三题

考察栈在种猪表达式转化为后缀表达式中的应用。

将中缀表达式a+b-a*((c+d)/e-f)+g转换为相应的后缀表达式,需要根据操作符<op>的优先级来进行栈的变化,我们用icp来表示当前扫描到的运算符ch的优先级,该运算符进栈后的优先级为isp,则运算符的优先级如下表所示:

isp)是栈内优先(in stack priority)数,icp是栈外优先(in coming priority)数。

操作符 # ( *,/ +,- )
isp 0 1 5 3 6
icp 0 6 4 2 1

我们在表达式后面加上‘#’,表示表达式结束,具体换换过程如下:

步骤 扫描项 项类型 动作 栈内内容 输出
isp 0 1 5 3 6
icp 0 6 4 2 1
0 #进栈,读下一符号 #
1 a 操作数 直接输出 # a
2 + 操作符 isp(‘#’) < icp(‘+’),进栈 #+
3 b 操作数 直接输出 #+ b
4 - 操作符 isp(‘+’) > icp(‘-‘),退栈并输出 # +
5 isp(‘#’) < icp(‘-‘),进栈 #-
6 a 操作数 直接输出 #- a
7 * 操作符 isp(‘-‘) < icp(‘*’)进栈 #-*
8 ( 操作符 isp(‘*’) < icp(‘(‘),进栈 #-*(
9 ( 操作符 isp(‘(‘) < icp(‘(‘),进栈 #-*((
10 c 操作数 直接输出 #-*(( c
11 + 操作符 isp(‘(‘) < icp(‘+’),进栈 #-*((+
12 d 操作数 直接输出 #-*((+ d
13 ) 操作符 isp(‘+’) > icp(‘)’),退栈并输出 #-*(( +
14 isp(‘(‘) == icp(‘)’),直接退栈 #-*(
15 / 操作符 isp(‘(‘) < icp(‘/’),进栈 #-*(/
16 e 操作数 直接输出 #-*(/ e
17 - 操作符 isp(‘/’) > icp(‘-‘),退栈并输出 #-*( /
18 isp(‘(‘) < icp(‘-‘),进栈 #-*(-
19 f 操作数 直接输出 #-*(- f
20 ) 操作符 isp(‘-‘) > icp(‘)’),退栈并输出 #-*( -
21 isp(‘(‘) == icp(‘)’),直接退栈 #-*
22 + 操作符 isp(‘*’) > icp(‘+’),退栈并输出 #- *
23 isp(‘-‘) > icp(‘+’),退栈并输出 # -
24 isp(‘#’) < icp(‘+’),进栈 #+
25 g 操作数 直接输出 #+ g
26 # 操作符 isp(‘+’) > icp(‘#’),退栈并输出 #
27 isp(‘#’) == icp(‘#’),退栈,结束

第四题

将中缀表达式转换后缀表达式的算法思想如下:
从左向右开始扫描中缀表达式;
遇到数字时,加入后缀表达式;
遇到运算符时:
a.若为‘(’,入栈;
b.若为‘)’,则一次把栈中的运算符加入后缀表达式中,直到出现‘(’,从栈中删除‘(’;
c.若为除括号外的其他运算符,当其优先级高于除‘(’意外的栈顶运算符时,直接入栈。否则从栈顶开始,一次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号位置。

当扫描的中缀表达式结束时,栈中的所有运算符一次出栈加入后缀表达式。

待处理序列 后缀表达式 当前扫描元素 动作
a/b+(c*d-e*f)/g a a加入后缀表达式
/b+(c*d-e*f)/g a / /入栈
b+(c*d-e*f)/g / a b b加入后缀表达式
+(c*d-e*f)/g / ab + +优先级低于栈顶的/,弹出/
+(c*d-e*f)/g ab/ + +入栈
(c*d-e*f)/g + ab/ ( (入栈
c*d-e*f)/g +( ab/ c c加入后缀表达式
*d-e*f)/g +( ab/c * 栈顶为(,*入栈
d-e*f)/g +(* ab/c d d加入后缀表达式
-e*f)/g +(* ab/cd - -优先级低于栈顶的,弹出
-e*f)/g +( ab/cd* - 栈顶为(,-入栈
e*f)/g +(- ab/cd* e e加入后缀表达式
*f)/g +(- ab/cd*e * *优先级高于栈顶的-,*入栈
f)/g +(-* ab/cd*e f f加入后缀表达式
)/g +(-* ab/cd*ef ) 把栈中(之前的符号加入表达式
/g + ab/cd*ef*- / /优先级高于栈顶的+,/入栈
g +/ ab/cd*ef*- g g加入后缀表达式
+/ ab/cd*ef*-g 扫描完毕,运算符一次退栈加入表达式
ab/cd*ef*-g/+ 完成

由此可知,当扫描到f的时候,栈中的元素一次是+(-*,选B。
再次再给出中缀表达式转换为前缀或后缀表达式的手工做法,以上面给出的中缀表达式为例:
第一步:按照运算符的优先级对所有的运算单位加括号
式子变成了:((a/b)+(((c*d)-(e*f)/g))

第二部:转换为前缀或后缀表达式。
前缀:把运算符号移动到对应的括号前面,则变成了:+(/(ab)/(-(*(cd)*(ef))g))
把括号去掉:+/ab/-*cd*efg前缀式子出现
后缀:把运算符移动到对应的括号 后面,则变成了:((ab)/(((cd)*(ef)*)-g/)+
把括号去掉:ab/cd*ef*-g/+ 后缀式子出现

当题目要求直接求前缀或后缀表达式时,这种方法会比上一中快捷的多。

猜你喜欢

转载自blog.csdn.net/qq_22073849/article/details/78416135