今天又看了中缀转后缀表达式的算法,才知道这个有名字交调度场算法(Shunting-yard algorithm,因过程类似火车编组场而得名),居然是Dijstra发明的,原来的贡献遍布CS各个角落。。。
之前知道Shortest path,银行家,PV,结构化程序设计之Goto危害
之前和一个实验室同事还讨论过这个问题,当初是不去看答案,自己推出这个算法,但是和最后的答案比较还是有问题。
为啥写这篇日志呢?
网上有很多版本,但是bug很多,wikipedia也有,但是涉及到过多的东西,包括函数,逗号之类的,对于绝大多数情况来说,过于复杂,不够好理解和实用。我决定写一篇比较实用然后bug尽量少(我不敢确定没有bug),注意此处是不考虑有开始符和结束符的表达式
这段代码可以处理包含若干 ( ) 嵌套, + - * / 等全部是二元运算的表达式,运算符可以左结合或者右结合。
之前知道Shortest path,银行家,PV,结构化程序设计之Goto危害
之前和一个实验室同事还讨论过这个问题,当初是不去看答案,自己推出这个算法,但是和最后的答案比较还是有问题。
为啥写这篇日志呢?
网上有很多版本,但是bug很多,wikipedia也有,但是涉及到过多的东西,包括函数,逗号之类的,对于绝大多数情况来说,过于复杂,不够好理解和实用。我决定写一篇比较实用然后bug尽量少(我不敢确定没有bug),注意此处是不考虑有开始符和结束符的表达式
transform 中缀表达式为后缀表达式(代码没有拘泥于实现细节,更注重与逻辑的设计)
Stack S;
while(not end of string)
{
str=current char;
if(str is a number)
{
show(str);
}
else if(str is ')')
{
//show(S.top()) and S.pop() until top() is '('
while(top() is not '(')//出现右括号,出栈直到出现左括号,因为优先级最高,且与( 唯一匹配关系
{
show(S.top());
S.pop();
}
S.pop();
}
else
{
if(S is not empty)//如果确保编译器处理 bool表达式 两个exp 做&&, 第一个 false就得出整个exp为false的话,这个if可以去掉,C C++多数都是这样,但保险起见还是写上了
{
while(S is not empty &&(S.top()'s priority is larger or equal to str when str is left association|| S.top()'s priority is larger to str when str is right association) && S.top() is not '(' )//如果出现相等优先级,如果做结合性,a+b-c,应该
先运算a+b,+先入站,因此要优于-号print出来;同理,相等优先级,如果右结合性,应当先算后面的,而后面的后入栈。但是为啥此时不是立即print str,而是压站呢?因为print出来也可以确保他在栈顶符号的前面。
这应该是Dijstra有一个数学上的理解吧,这样才能保证正确性。此外遇到栈顶为( 则退出循环,( 特殊,只有与)匹配才会出栈。由此也可得:操作符必须至少进过栈才会被print出来。这一性质可以考虑作为循环不变性来证明算法的性质。
{
show(S.top());//之前栈的符号依次出来,后进的先出,因为前面确保了上面的优先级会高,所以先出栈'运算'
S.pop();
}
}
S.push(str);//如果占空,将str压站;若出现栈顶优先级更小,也将str压站
}
}
while(S is not empty)//将最后栈的运算符出栈。此处运算符包括最后一个运算符,或者位于前面的比最后一个运算符低优先级的运算符。栈保持了上方运算符优先级较高的特性。
{
show(S.top());
S.pop();
}
这段代码可以处理包含若干 ( ) 嵌套, + - * / 等全部是二元运算的表达式,运算符可以左结合或者右结合。
个人感觉 知道这个思路写算法的难度,相比与当初Dijstra设计这个算法简直是九牛一毛,我猜当初设计一定遇到了很多问题,并且用严谨的数学思想例如断言之类的进行过证明。。。
ref: http://zh.wikipedia.org/wiki/%E8%B0%83%E5%BA%A6%E5%9C%BA%E7%AE%97%E6%B3%95
http://hi.baidu.com/pluto455988971/item/6b5bcb253d61bc4147996262#e40ef69279a9af8a59146162 这位仁兄还和我进行了愉快的讨论~~