1、波兰表达式求解,tangchenxing 2006.4.9,程序=数据结构+算法,背景知识,后缀形式(波兰形式)的表达式与通常的中缀形式的表达式不同。在后缀形式的表达式中,2元运算的运算符出现在2个变量之后。例如,通常的表达式“a+b”,用后缀形式表示为“a b +”。在通常的中缀形式的表达式中,需要用括号来表示运算的优先级。而在后缀形式的表达式中,不需要用括号来表示运算的优先级,只要依次从左到右计算。,i2p编程任务,给定一个中缀形式的表达式,将其变换为等价的后缀形式的表达式。,例如,中缀形式的表达式 “15*(9+8)*(4+6)+7)” 的后缀形式为 “15 9 8 + 4 6 * *
2、7 + *”。,Expr编程任务,给定一个后缀形式的表达式,编程计算其值。,把两个问题和并起来,就是表达式的中缀化后缀,后缀化输出. 即给你一个表达式,输出它的解.,http:/ expression evaluation,算法分析,波兰表达式是一个经典问题 算法大致分为两种: a) 通过对栈的操作完成. 通过优先级别中序遍历建立2叉树,然后用后序遍历一下求解,算法复杂度为O(n),波兰表达式i2p中缀化后缀 堆栈解,观察一个中缀表达式A+B*(C-D)/E+F,表达式中的数字的相对位置没有变化,位置变化的只是符号的位置,其后缀表达式为A B C D - * E / + F +,因此我们建立一
3、个符号栈SymbolStack就够了.,为了便于处理我在表达式前后各加了一个( , ) 作为 “哨兵”. 通过简单的观察后,我们可以定义符号的优先级别:,数字: 直接进入答案数组ans+p; ( : 无须考虑任何东西,直接进入符号栈 ) : 无须入栈,pop出栈中的元素,直到pop出一个(为止. +,- :pop清空SymbolStack直到遇到(,然后+ or 再入栈, *,/,%: pop清空SymbolStack直到遇到 (,+,-,然后操作符再入栈.凡是pop出的符号除(外,其他的都进入答案数组ans+p;,现在产生一个问题.ans数组既要放数字,又要放符号.出现冲突了!,解决方法1:
4、将ans数组定义成long ansM; 将-2,000,000,000之后的数自定义成符号 如-2,000,000,001代表符号+-2,000,000,002代表符号- ,解决方法2: ans定义成字符数组,用空格分割数字和字符.,核心代码: for(i=0;iStringLen;i+)if (isspace(sti) continue;else if (isdigit(sti)tmp=0;while(isdigit(sti)tmp=tmp*10+sti-0;i+;i-;NumStack+p1=tmp;,elseswitch (sti) /checkcase +: case -: /+,-w
5、hile(SymbolStackt1!=()NumStack+p1=SymbolStackt1+MMIN;SymbolStackt1-=0;SymbolStack+t1=sti;break;,case *:case /: /*,/while(SymbolStackt1=* | SymbolStackt1=/)NumStack+p1=SymbolStackt1+MMIN;SymbolStackt1-=0;SymbolStack+t1=sti;break;,case (: /(SymbolStack+t1=sti;break;case ): /)while(SymbolStackt1!=()Num
6、Stack+p1=SymbolStackt1+MMIN;SymbolStackt1-=0;SymbolStackt1-=0; /popbreak; ,波兰表达式i2p后缀化输出,数字进栈,遇到操作符,pop出两个元素num1,num2. 通过cal(num1,num2,workchar)函数计算一下运算结果.将结果进栈. 如果表达式合法的话,最后栈中必然只剩下一个元素,输出即可.,只要一个堆栈判断一下就搞定了。,附加说明: 本人比较懒惰,用数组模拟栈,代码很短. for(i=1;i=p1;i+)if (NumStacki0) tmp=calculator(stackp-1,stackp,NumStacki-MMIN);stackp=0;p-;stackp=tmp; /pop_stackelse stack+p=NumStacki; /push_stack ,Mission Complete!,