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

来源:互联网 发布:汇编怎么写网络程序 编辑:程序博客网 时间:2024/06/05 11:06

习题部分

选择题

第一题

一个问题的递归算法求解和其相对应的非递归算法求解()
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/+ 后缀式子出现

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

原创粉丝点击