【Java数据结构的实现】之系列三栈的实现(使用栈计算后缀表达式)
上讲介绍了栈的介绍,最后并给出了栈的抽象数据类型
1.1本章学习目标
- 中、后缀表达式简介
- 后缀表达式的实现
本文介绍了栈的实例--使用栈计算后缀表达式:
1.2 中、后缀表达式简介
①中缀表达式:
通常,算术表达式写作中缀表达式,,什么是中缀表达式呢?中缀表达式就是:操作符位于操作数之间。
如下形式:
<操作数><操作符><操作数>
例如表达式:1+2*3,计算时,我们根据表达式的优先规则来计算。其结果是7而不是9.
那什么是后缀表达式呢?
②后缀表达式:
后缀表达式就是:操作符位于两个操作数之后,后缀表达式的形式如下:
<操作数><操作数><操作符>
如下所示:
- 1 2 - 等价于1-2
③使用后缀表达式的优点:
后缀表达式比中缀表达式更容易计算,因为它不用考虑优先规则和括弧,表达式中的操作数和操作符的顺序就足以完成计算。
因此程序设计语言编辑器和运行时环境在其内部中往往使用后缀表达式。
④后缀表达式的计算规则:
后缀表达式的计算过程可以概括如下:
从左到右扫描整个表达式,把每个操作符应用到其之前两个相邻的操作数,并计算该结果,剩下的表达式以此类推。
1+2*3
可以转换成后缀表达式如下:
1 2 3 * +
计算过程如下:
1 2*3 + --> 1 6 + -->7
更复杂的后缀表达式,亦是如此规则。由此可以发现,栈是用于计算后缀表达式的理想数据结构。
1.3 后缀表达式的实现
①程序设计的思路:
- /**
- * 从左到右扫描表达式,以此标识出每个符号(操作数或操作符)。如果是操作数,
- * 则把它压入栈中。如果是操作符,则从栈中弹出两个元素,
- * 并把该操作符应用在这两个元素只上,然后把操作结果压入栈中。
- * 当到达表达式的末尾时,栈中所神域的元素就是该表达式的计算结果。
- * @param expr 后缀表达式
- * @return int 后缀表达式的值
- * */
程序运行时,会提示用户反复输入操作数和操作符,中间已空格隔开。
②程序关键部位均有详细的注释!
- import java.util.Stack;
- /**
- * 计算后缀表达式,假定操作数都是常量
- * */
- public class PostfixEvaluator {
- /**+号标识*/
- private final char ADD = '+';
- /**-号标识*/
- private final char SUBTRACT = '-';
- /***号标识*/
- private final char MULTIPLY = '*';
- /**除号标识*/
- private final char DIVIDE = '/';
- /**栈*/
- private Stack<Integer> stack;
- /**创建一个新栈*/
- public PostfixEvaluator(){
- stack = new Stack<Integer>();
- }
- /**
- * 从左到右扫描表达式,以此标识出每个符号(操作数或操作符)。如果是操作数,
- * 则把它压入栈中。如果是操作符,则从栈中弹出两个元素,
- * 并把该操作符应用在这两个元素只上,然后把操作结果压入栈中。
- * 当到达表达式的末尾时,栈中所神域的元素就是该表达式的计算结果。
- * @param expr 后缀表达式
- * @return int 后缀表达式的值
- * */
- public int evaluate(String expr){
- int op1,op2,result=0;
- String token;
- //将字符串分解,\s 匹配任何空白字符,包括空格、制表符、换页符等。
- String[] tokenizer = expr.split("\\s");
- for (int x = 0; x < tokenizer.length; x++){
- System.out.print(tokenizer[x]+" ");//输出
- token = tokenizer[x];
- if(isOperator(token)){//判断是操作符,则出栈两个操作数
- op2 = (stack.pop()).intValue();
- op1 = (stack.pop()).intValue();
- result = evalSingleOp (token.charAt(0),op1,op2);//计算结果
- stack.push(new Integer(result));//把计算结果压入栈中
- }else {
- stack.push(new Integer(Integer.parseInt(token)));//压入操作数
- }
- }
- return result;
- }
- /**
- * 计算
- * @param1 op1 第一个操作数
- * @prama2 op2第二个操作数
- * @return 计算的结果
- *
- * */
- private int evalSingleOp(char operation, int op1, int op2) {
- int result = 0;
- switch(operation)
- {
- case ADD:
- result = op1+op2;
- break;
- case SUBTRACT:
- result = op1-op2;
- break;
- case MULTIPLY:
- result = op1*op2;
- break;
- case DIVIDE:
- result = op1/op2;
- break;
- }
- return result;
- }
- /**
- * 判断是否为操作符
- * @param token
- * @return boolean
- * */
- private boolean isOperator(String token) {
- return (token.equals("+")||token.equals("-")||
- token.equals("*")||token.equals("/"));
- }
- }
③ 测试方法:
- import java.util.Scanner;
- /**
- *
- * 计算后缀表达式
- * */
- public class Postfix {
- /**
- * @param args
- */
- public static void main(String[] args) {
- String expression,again;
- int result;
- try {
- Scanner in = new Scanner(System.in);
- do {
- PostfixEvaluator evaluator = new PostfixEvaluator();
- System.out.println("请输入一个后缀表达式");
- expression = in.nextLine();
- result = evaluator.evaluate(expression);//
- System.out.println();
- System.out.println("计算结果为:"+result);
- System.out.println("计算另外一个表达式【Y/N】?:");
- again = in.nextLine();
- if(again.equalsIgnoreCase("n")){
- System.out.println("计算退出!");
- }
- System.out.println();
- }while (again.equalsIgnoreCase("y"));
- }catch(Exception e) {
- e.printStackTrace();
- System.out.println("输入异常,请正确输入后缀表达式,并以空格区分");
- }
- }
- }
④测试结果:
- /**
- * 请输入一个后缀表达式
- 3 4 * 2 5 + - 4 * 2 /
- 3 4 * 2 5 + - 4 * 2 /
- 计算结果为:10
- 计算另外一个表达式【Y/N】?:
- *
- * */
本文转自 w156445045 51CTO博客,原文链接:http://blog.51cto.com/enetq/713534,如需转载请自行联系原作者