1、前言
Shunting yard算法(调度场算法)是一个用于将中缀表达式转换为后缀表达式的经典算法,由艾慈格.迪杰斯特拉引入,因其操作类似于火车编组场而得名。
例如:3+4
1)将3入输出队列(每当输入一个数字时,直接进入输出队列)
2)将+号压入运算堆栈
3)将4入输出队列
4)输入结束,将操作符堆栈中剩余操作符入输出队列
通过这个例子可以简单的看出两个规则:
- 当读入一个数字时,直接入输出队列
- 当输入结束后,运算符队列中所有操作符入输出队列
二、详细的算法
提示:我们将分配一个队列和一个栈,队列主要用于输出后缀表达式,然而栈主要用于保存操作符。
1、读入一个记号
- 如果该记号为数字,直接将其放到输出队列中;
- 如果该记号为一个操作符o,则将其与栈顶比较;
如果栈顶为空,直接将该操作符o压入栈;
如果该操作符o是左结合性的,
栈顶的操作符o的优先级大于或等于该操作符的优先级,则弹出栈顶的操作符,然后将操作符o压入栈。否则不弹出,并将操作符o压入栈。
如果该操作符是右结合性的,
栈顶的操作符的优先级大于该操作符的优先级,则弹出栈顶的操作符,然后将该操作符压入栈。否则不弹出,并将操作符o压入栈。
如果该操作符是左括号,那么将其压入栈;
如果该操作符是右括号,那么从栈当中不断弹出操作符并且放入输出队列中,直到栈顶元素为左括号为止。
2、重复执行
3、当再没有记号可以读取时:则弹出栈中剩下的操作符。
输入: 3 + 4 * 2 / ( 1 − 5 ) ^ 2 ^ 3
输入 动作 输出(逆波兰表达式) 运算符栈 提示 3 将符号加入输出队列 3 + 将符号压入操作符堆栈 3 + 4 将符号加入输出队列 3 4 + * 将符号压入操作符堆栈 3 4 *+ *号的优先级高于+号 2 将符号加入输出队列 3 4 2 *+ / 将堆栈中元素弹出,加入输出队列;
将符号压入操作符堆栈3 4 2 *;
3 4 2 *+;
/ +
/号和*号优先级相同;
/号的优先级高于+号( 将符号压入操作符堆栈 3 4 2 * ( / + 1 将符号加入输出队列 3 4 2 * 1 ( / + - 将符号压入操作符堆栈 3 4 2 * 1 − ( / + 5 将符号加入输出队列 3 4 2 * 1 5 − ( / + ) 将堆栈中元素弹出,加入输出队列;
将堆栈元素弹出3 4 2 * 1 5 −;
3 4 2 * 1 5 −( / +
/ +循环直到找到(号;
括号匹配结束^ 将符号压入操作符堆栈 3 4 2 * 1 5 − ^ / + ^号的优先级高于/号 2 将符号加入输出队列 3 4 2 * 1 5 − 2 ^ / + ^ 将符号压入操作符堆栈 3 4 2 * 1 5 − 2 ^ ^ / +
^号为从右至左求值 3 将符号加入输出队列 3 4 2 * 1 5 − 2 3 ^ ^ / + END 将栈中所有数据加入输出队列 3 4 2 * 1 5 − 2 3 ^ ^ / +
参考于:http://zh.wikipedia.org/wiki/Shunting_yard%E7%AE%97%E6%B3%95
介绍一个人工转换的方法,假设有一个中缀表达式a+b*c-(d+e)
1首先将这个中缀表达式的所有运算加括号((a+(b*c))-(d+e))
2然后将所有运算符放到括号后面,这样就变成了((a(bc)* )+ (de)+ )-
3把所有括号去掉abc*+de+-,最后得出的结果就是后缀表达式
上面这个方法可以在比如做题分析的时候用人脑的时候使用,接下来介绍用程序实现将中缀转换成后缀表达式的思路
参考于:http://www.cnblogs.com/MichaelYin/archive/2012/05/02/2479248.html