标签:
最近学习了栈,为了巩固知识,照着书实现了一个有关于栈的应用的例子:将中缀表达式转化为后缀表达式。
这里先来明白什么是中缀表达式:我们正常使用的算式,如a + b * c 就是一个中缀表达式。中缀表达式的特点就是运算符在中间。
后缀表达式就是 运算符在后面,像上面的式子如果转化为后缀表达式就为 a b * + 。
这里以测试用例:A*B(B+C)-D/(E+F) 来为大家介绍一下转化的过程。
由中缀表达式中读取的字符 |
分解中缀表达式的过程 |
求后缀表达式的过程 |
栈中的内容 |
规则 |
A |
|
A |
|
将操作数A写至后缀(后缀表达式) |
* |
A* |
A |
* |
若栈为空,将*进栈 |
( |
A*( |
A |
*( |
将操作数(入栈 |
B |
A*(B |
AB |
*( |
将操作数B写入后缀 |
+ |
A*(B+ |
AB |
* |
栈非空,故弹出一项 |
|
A*(B+ |
AB |
*( |
有(,故将(进栈 |
|
A*(B+ |
AB |
*(+ |
将操作数+进栈 |
C |
A*(B+C |
ABC |
*(+ |
将操作数C写入后缀中 |
) |
A*(B+C) |
ABC+ |
*( |
遇见),弹出栈中的位于(之后的内容即+,写至后缀 |
|
A*(B+C) |
ABC+ |
* |
若有(,直接将其出栈 |
- |
A*(B+C) |
ABC+* |
- |
将*出栈,写入后缀,再将-进栈 |
D |
A*(B+C)-D |
ABC+*D |
- |
将D写入后缀 |
/ |
&-D/ |
&D |
-/ |
将\进栈 |
( |
&-D/( |
&D |
-/( |
将(入栈 |
E |
&-D/(E |
&DE |
-/( |
将E写入后缀 |
+ |
&-D/(E+ |
&DE |
-/ |
栈弹出一项 |
|
&-D/(E+ |
&DE |
-/( |
出栈的为(,因此将其重新进栈 |
|
&-D/(E+ |
&DE |
-/(+ |
将+进栈 |
F |
&-D/(E+F |
&DEF |
-/(+ |
将F写入后缀 |
) |
&-D/(E+F) |
&DEF |
-/( |
遇见),弹出栈中的位于(之后的内容即+,写至后缀 |
|
&-D/(E+F) |
&DEF+ |
-/ |
遇见(,将其出栈 |
|
&-D/(E+F) |
&DEF+/- |
|
将剩下栈中的元素全部出栈,写入后缀 |
A*(B+C)-D/(E+F)
如果大家肯定还不太明白,大家可以自己百度一下,这里就不多做介绍了。
实现的算法就是上面的转化过程,下面是源码,包含解释:
1.栈类stackX
package infix; /* * 这是一个自己定义的,存储数据的栈 */ public class StackX { private int maxSize; private char[] stackArray; private int top; public StackX(int s){ maxSize = s; stackArray = new char[maxSize]; top = -1; } //入栈操作 public void push(char value){ stackArray[++top] = value; } //出栈操作 public char pop(){ return stackArray[top--]; } //查看栈顶元素 public char peek(){ return stackArray[top]; } //判断是是否为空 public boolean isEmpty(){ return (top == -1); } public int size(){ return top+1; } //查看在位置n的元素 public char peekN(int n){ return stackArray[n]; } //打印从栈底到栈顶的元素 public void displayStack(String s){ System.out.print(s); System.out.print("Stack (bottom-->top):"); for (int j = 0; j < size(); j++) { System.out.print(peekN(j)); System.out.print(‘ ‘); } System.out.println(""); } }
2.InToPost类,存放的操作方法
package infix; public class InToPost { private StackX stack; private String input; private String output=""; public InToPost(String in){ input = in; //输入的要分析的字符串 int stackSize = input.length(); stack = new StackX(stackSize); } /* * 将中缀表达式转化为后缀表达式 * 如果读取的单个字符不是基础运算符,则将这个字符放入output中。output中的数据只会增加,不会变化 */ public String doTrans(){ for (int i = 0; i < input.length(); i++) { char ch = input.charAt(i); //从input中取出第i个字符 stack.displayStack("For " + ch + " "); //调用StackX中的方法来显示ch switch (ch) { case ‘+‘: case ‘-‘: gotOper(ch, 1); break; case ‘*‘: case ‘/‘: gotOper(ch, 2); break; case ‘(‘: stack.push(ch); break; case ‘)‘: gotParen(ch); break; default: output = output + ch; break; } } //将剩余的栈中元素全部出栈。出栈的顺序就代表了运算的顺序。 while(!stack.isEmpty()){ stack.displayStack("While "); output = output + stack.pop(); } stack.displayStack("End "); return output; } public void gotOper(char opThis, int prec1){ while (!stack.isEmpty()) { //循环将栈中的char类型出栈 char opTop = stack.pop(); if (opTop == ‘(‘) { stack.push(opTop); //将出栈的‘(’元素进栈 break; }else { int prec2; //判断onTop的优先级 if (opTop==‘+‘||opTop == ‘-‘) { //设置加减的优先级为1 prec2 = 1; }else { //其他的优先级为2 prec2 = 2; } if (prec2 < prec1) { //当传入的onThis的优先级prec1大于出栈的opTop的优先级 stack.push(opTop); //将出栈的opTop进栈 break; }else { output = output + opTop; //如果出栈的opTop的算术优先级比opThis的大,则将其放到output中 } } } stack.push(opThis); } public void gotParen(char ch){ while (!stack.isEmpty()) { char chx = stack.pop(); //读取到‘(’,就出栈在‘(’和‘)’之间的所有元素 if (chx == ‘(‘) { break; }else { output = output + chx; //如果读到了‘)’,则将stack栈中的符号放入output中 } } } }
3.主类:
package infix; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /* * 用栈来实现把一个中缀表达式,转化为一个后缀表达式 */ public class InfixApp { public static void main(String[] args) throws IOException { String input,output; while(true){ System.out.println("输入要运算式: "); System.out.flush(); input = getString(); if (input.equals("")) { System.out.println("输入不要为空"); break; } //创建InToPost对象 InToPost theTrans = new InToPost(input); //调用doTrans方法 output = theTrans.doTrans(); System.out.println("转化后的运算式为: " + output + ‘\n‘); } } //用于读取输入流中的数据 public static String getString() throws IOException{ InputStreamReader in = new InputStreamReader(System.in); BufferedReader buffer = new BufferedReader(in); String s = buffer.readLine(); return s; } }
运行结果:
输入要运算式: A*(B+C)-D/(E+F) For A Stack (bottom-->top): For * Stack (bottom-->top): For ( Stack (bottom-->top):* For B Stack (bottom-->top):* ( For + Stack (bottom-->top):* ( For C Stack (bottom-->top):* ( + For ) Stack (bottom-->top):* ( + For - Stack (bottom-->top):* For D Stack (bottom-->top):- For / Stack (bottom-->top):- For ( Stack (bottom-->top):- / For E Stack (bottom-->top):- / ( For + Stack (bottom-->top):- / ( For F Stack (bottom-->top):- / ( + For ) Stack (bottom-->top):- / ( + While Stack (bottom-->top):- / While Stack (bottom-->top):- End Stack (bottom-->top): 转化后的运算式为: ABC+*DEF+/- 输入要运算式:
标签:
原文地址:http://www.cnblogs.com/mercuryli/p/5011151.html