栈的应用举例

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

[程序清单] program ex2(input,output); const max=100; op_set:set of char=['+','-','*','/']; letter:set of char=['A'..'Z']; var expression,result:string; procedure scan(expression:string); var i,top1,top2:integer; ovs:array [1..max] of string[max]; ops:array [1..max] of char; f:array['#'..'/','#'..'/'] of shortint; begin f['+','+']:=1; f['+','-']:=1; f['+','*']:=-1; f['+','/']:=-1; f['+','(']:=-1; f['+',')']:=1; f['+','#']:=1; f['-','+']:=1; f['-','-']:=1; f['-','*']:=-1; f['-','/']:=-1; f['-','(']:=-1; f['-',')']:=1; f['-','#']:=1; f['*','+']:=1; f['*','-']:=1; f['*','*']:=1; f['*','/']:=1; f['*','(']:=-1; f['*',')']:=1; f['*','#']:=1; f['/','+']:=1; f['/','-']:=1; f['/','*']:=1; f['/','/']:=1; f['/','(']:=-1; f['/',')']:=1; f['/','#']:=1; f['(','+']:=-1;f['(','-']:=-1;f['(','*']:=-1; f['(','/']:=-1; f['(','(']:=-1; f['(',')']:=0; f['(','#']:=2; f[')','+']:=2; f[')','-']:=2; f[')','*']:=2; f[')','/']:=2; f[')','(']:=2; f[']',')'):=2; f[']','#'):=2; f['#','+']:=-1;f['#','-']:=-1;f['#','*']:=-1; f['#','/']:=-1; f['#','('):=-1; f['#',']']:=2; f['#','#']:=0; expression:=expression+'#'; ops[1]:='#';
top1:=0; top2:=1; for i:=1 to length(expression) do {逐个扫描} begin if expression[i] in letter {是字母就进栈} then begin top1:=top1+1; ovs[top1]:=expression[i] end else begin {运算符} while f[ops[top2],expression[i]]=1 do {栈顶运算符优先级高于当前运算符} begin {取栈顶上面的两个元素运算后,再压栈} ovs[top1-1]:=ovs[top1-1]+ovs[top1]+ops[top2]; top1:=top1-1; top2:=top2-1 end; if f[ops[top2],expression[i]]=0 then top2:=top2-1 {优先级相同,则抵消} else begin top2:=top2+1;{栈顶运算符优先级低于当前运算符, 则压栈} ops[top2]:=expression[i] end; end end; result:=ovs[1] {返回结果} end; begin{main} write('Input a expression:'); readln(expression); scan(expression); writeln('The result is: ',result) end. [测试数据] 输入:A*(X+Y)/(B-Z) 输出:AXY+*BZ-/ [深入思考] 其实这是一个较好的“万能算法” 。因为上述算法还可用于求一个表达式的值(输入一 个中缀表达式,只含有 0-9 组成的运算数及加(+) 、减(—) 、乘(*) 、除(/)四种运算符 和圆括号, 不要转换成后缀表达式而直接用栈求值) ; 也可以判断一个表达式是否有错等等。 请学员们自己上机编程实现。 例3、 编程求一个后缀表达式的值 [问题描述]
栈的应用举例(栈与表达式处理)
[引言] 处理表达式是高级语言编绎中的一个基本问题。 它的实现是栈的一个重要应用, 通过对 表达式的处理讨论,可以帮助我们进一步了解栈的性能。 [内容讲授] 栈在计算机科学领域有着广泛的应用。 比如在编译和运行计算机程序的过程中, 就需要 用栈进行语法检查(如检查 begin 和 end、 “ (”和“) ”等是否匹配) 、计算表达式的值、实 现过程和函数的递归调用等。下面举例说明栈在这些方面的应用。 例1、 括号的匹配(表达式的合法性检查) [问题描述] 假设一个表达式有英文字母(小写) 、运算符(+,—,*,/)和左右小(圆)括号构成, 以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹 配,则返回“YES” ;否则返回“NO” 。表达式长度小于 255,左圆括号少于 20 个。 [问题分析] 假设输入的字符串存储在 c 中(var c:string[255]) 。 我们可以定义一个栈:var s:array[1..maxn] of char; top:integer; 用它来存放表达式中从左往右的左圆括号(maxn=20) 。 算法的思路为:顺序(从左往右)扫描表达式的每个字符 c[i],若是“ (” ,则让它进 栈;若遇到的是“) ” ,则让栈顶元素出栈;当栈发生下溢或当表达式处理完毕而栈非空时, 都表示不匹配,返回“NO” ;否则表示匹配,返回“YES” 。 [程序代码] program ex1; const maxn=20; var c:string; function doit(c:string):boolean; var s:array[1..maxn] of char; top,i:integer; ch:char; begin top:=0; i:=1;ch:=c[i]; while ch<>'@' do begin if (ch='(') or (ch=')') then case ch of '(' : begin top:=top+1;s[top]:='(' end; ')' : if top>0 then top:=top-1
从键盘读入一个后缀表达式(字符串) ,只含有 0-9 组成的运算数及加(+) 、减(—) 、 乘(*) 、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式 是否合法。 [问题分析] 后缀表达式的处理过程很简单,过程如下:扫描后缀表达式,凡遇操作数则将之压进堆 栈,遇运算符则从堆栈中弹出两个操作数进行该运算,将运算结果压栈,然后继续扫描,直 到后缀表达式被扫描完毕为止,此时栈底元素即为该后缀表达式的值。 [参考程序] program ex3; const maxn=20; var stack:array[1..maxn] of integer; s:string; function comp(s:string):integer; var ch:char; i,top,x,y,z:integer; begin top:=0; i:=1; ch:=s[i]; while i<=length(s) do begin case ch of '0'..'9':begin x:=0; while ch<>' ' do begin x:=x*10+ord(ch)-ord('0'); i:=i+1; ch:=s[i]; end; top:=top+1; stack[top]:=x; '+' '-' '*' '/' end; :begin x:=stack[top];top:=top-1;y:=stack[top];z:=y+x;stack[top]:=z end; :begin x:=stack[top];top:=top-1;y:=stack[top];z:=y-x;stack[top]:=z end; :begin x:=stack[top];top:=top-1;y:=stack[top];z:=y*x;stack[top]:=z end; :begin x:=stack[top];top:=top-1;y:=stack[top];z:=y div x;stack[top]:=z end;
入的中缀表达式的运算次序一致。为简单起见,假设输入的中缀表达式由+(加) 、-(减) 、 *(乘) 、/(除)四个运算符号以及左右圆括号和大写英文字母组成,其中算术运算符遵守 先乘除后加减的运算规则。假设输入的中缀表达式长度不超过 80 个字符,且都是正确的, 即没有语法错误,并且凡出现括号其内部一定有表达式,即括号内部至少有一个运算符号。 以下是一个运行实例。 [样例输入] X+A*(Y-B)-Z/F [样例输出] XAYB-*+ZF/-
Biblioteka Baidu
[算法设计] 设置两个栈:操作数栈(ovs)和运算符栈(ops) ,用来分别存放表达式中的操作数和 运算符。开始时操作数栈为空,运算符栈中放入一个特殊的标志运算符号#号,并在表达式 的末尾相应地加上一个#号,并规定#号的 优先级最低,然后从左向右扫描表达式, 凡遇操作数便一律进栈;若遇运算符,则 判断其优先级是否大于运算符栈栈顶元素 的优先级。若小,则栈顶运算符退栈,并 从操作数栈中弹出两个操作数(操作数为 后缀表达式)进行后缀变换处理,处理结 果进操作数栈,重复刚才的比较,直到栈 顶运算符的优先级大于等于当前运算符的 优先级;此时,若当前运算符的优先级大 于栈顶运算符的优先级,则当前运算符进 栈,继续扫描;若当前运算符的优先级等 于栈顶运算符的优先级,则弹出栈顶运算 符,继续扫描。扫描完该表达式后运算符 栈为空,操作数栈中只有一个元素,该元 素就是所要求的后缀表达式。 右图是对范例表达式的扫描示意图: 这样,我们需要事先把所有运算符号 的优先级定义并存放好,这很简单,以下 程序中的数组 f 就是用来存放运算符之间的优先级关系的。 1(>)表示前面的运算符优先于后 面的运算符,-1(<)表示后面的运算符优先于前面的运算符,0(=)表示前面的运算符的优先 级与后面的运算符相同, 2(ERROR)表示这两个运算符如果在扫描中相遇的话, 意味着该表达 式是错误的。 需要补充的是:左括号的优先级是最高的,而里层的左括号比外层的左括号更优先,右 括号的优先级是除#号以外最低的,但左括号和右括号的优先级则是相等的,这样定义的目 的是为了消去括号。
else begin doit:=false;exit end; end; i:=i+1;ch:=c[i]; end; if top=0 then doit:=true else doit:=false; end; begin {mian} assign(input,'in.txt'); reset(input); readln(c); writeln(doit(c)); close(input); end. [关于表达式的三种表示法] 1、 中缀表达式:a+b 2、 后缀表达式:ab+ 3、 前缀表达式:+ab 4、 中缀转后缀的方法及举例转换: ①把每个运算符移到它的两个运算数后面,每个运算数后多加上一个空格(为了分 隔各个运算数) ,然后去掉所有括号即可。如: 3/5+6——————————3□5□/□6□+ {□表示空格, 下同} 16-9*(4+3)—————— 16□9□4□3□+*2*(x+y)/(1-x)———————2□x□y□+*1□x□-/ (25+x)*(a*(a+b)+b)———— 25□x□+a□a□b□+*b□+* ②表达式树:表达式树(二叉树)结合先序、中序和后序遍历,举例。 5、 中缀表达式的运算规则比较多,包括优先级、左右次序和括号;尤其是括号可以改 变优先顺序,这就只能在计算的每一步,用肉眼去扫描、观察和比较整个表达式中 谁的优先级高,就先计算那一部分。但用计算机去做就很麻烦,而且效率不高。所 以,计算机科学中是把中缀表达式先转换成后缀表达式,在利用计算机来计算后缀 表达式的值。后缀表达式又称“逆波兰式” ,在后缀表达式中,不存在括号,也不 存在优先级的差别,计算过程完全按照运算符出现的先后顺序进行,整个计算过程 仅需一遍扫描即可完成。 6、两个编程任务: (1)把中缀表达式转换成后缀表达式; (2)求后缀表达式的值; 例2、 中缀表达式转换成后缀表达式 [问题描述] 输入一个中缀表达式, 编程输出其后缀表达式, 要求输出的后缀表达式的运算次序与输
以上规律列表如下: P2 P1 + * / ( ) # + > > > > < > < > > > > < > < * < < > > < > < / < < > > < > < ( < < < < < ERROR < ) > > > > = > ERROR # > > > > ERROR > =
相关文档
最新文档