栈的重要应用之中缀转后缀表达式算法

今天又看了中缀转后缀表达式的算法,才知道这个有名字交调度场算法(Shunting-yard algorithm,因过程类似火车编组场而得名),居然是Dijstra发明的,原来的贡献遍布CS各个角落。。。
之前知道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 这位仁兄还和我进行了愉快的讨论~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值