java中的栈Stack的基本使用和应用(二) ——利用栈计算合法的算术表达,中缀表达式转后缀表达式

利用栈Stack计算合法的算术表达式

限定的算术表达式求值问题:包含  “+”、“-”、“*”、“/”  、正整数和圆括号的合法算术表达式。

算术表达式转化成后缀表达式

程序语言中,运算符在两个运算数中间称为中缀表达式,即我们常用的表达方法,例如 1+2*3。

在中缀表达式中要考虑运算的优先级,先乘除,后加减,从左到右,还有括号内先运算。

在后缀表达式中已经考虑了运算符的优先级,并且没有括号,只有运算数和运算符。

例如上述例子 1+2*3 ,中缀表达式计算时,根据优先级,先计算2*3=6,再计算1+6=7

转换成后缀表达式   1+2*3 => 123*+ ,

从左到右扫描第一个运算符为 * ,先执行2*3;第二个运算符为 + ,执行1+6.

中缀表达式转后缀表达式过程

①初始化exp字符数组、resultExp字符数组(可变)、operator栈

  exp字符数组:存放,合法的算术表达式

  resultExp字符数组(可变):存放后缀表达式

  operator栈:存放运算符,并将 “=” 作为栈底元素

②从exp读取字符ch,若为运算数将后续运算数依次存放入resultExp中,并以#标志数值结束

③若ch为运算符,将其和operator栈顶中的运算符进行比较优先级比较

  ch优先级大于栈顶运算符优先级,则ch进栈

  ch优先级小于栈顶运算符优先级,则栈中运算符退栈,直至ch运算符大于栈顶运算符,ch再进栈。

  ch优先级等于栈顶运算符优先级,特殊情况,只有括号满足该情况,即“)”的优先级 等于“(”的优先级,将(退栈。

④exp扫描完毕,此时operator栈不空,则将 “=” 之前所有的运算符退栈并放入resultExp中

复杂一点的例子

(12-3)/(4+5)

算法如下:

package com.xumz.stack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
 * 中缀表达式转后缀表达式
 * 
 * @author xumz 2017/10/18
 */
public class ExpressionChange {
    // 存放左运算符的优先级
    Map<Character, Integer> leftOperator = new HashMap<Character, Integer>() {
        {
            put('=', 0);
            put('(', 1);
            put('+', 3);
            put('-', 3);
            put('*', 5);
            put('/', 5);
            put(')', 6);
        }
    };
    // 存放右运算符的优先级
    Map<Character, Integer> rightOperator = new HashMap<Character, Integer>() {
        {
            put('=', 0);
            put('(', 6);
            put('+', 2);
            put('-', 2);
            put('*', 4);
            put('/', 4);
            put(')', 1);
        }
    };

    /**
     * 中缀转后缀
     * 
     * @param str
     * @return
     */
    public String trans(String str) {
        // 转换成char[]
        char[] exp = str.toCharArray();
        // 存放转换结果
        List<Character> resultExp = new ArrayList<Character>();
        // 存放运算符,初始底为‘=’
        Stack<Character> operator = new Stack<Character>();
        operator.push('=');
        // 扫描exp表达式
        int i = 0;
        while (i != exp.length) {
            // 数字情况
            if (!isOperator(exp[i])) {
                while (i != exp.length && !isOperator(exp[i])) {
                    resultExp.add(exp[i]);
                    i++;
                }
                resultExp.add('#');
            }
            // 运算符情况
            else {
                switch (compareOperatorNice(operator.peek(), exp[i])) {
                case -1:
                    operator.push(exp[i]);
                    i++;// 继续下一个字符
                    break;
                case 0:
                    operator.pop();
                    i++;// 继续下一个字符
                    break;
                case 1:
                    resultExp.add(operator.peek());
                    operator.pop();
                    break;
                }
            }

        }
        while (!(operator.peek()=='=')) {
            resultExp.add(operator.peek());
            operator.pop();
        }
        

        // 转换为String返回
        return resultExp.toString();
    }

    boolean isOperator(char ch) {
        if (leftOperator.containsKey(ch)) {
            return true;
        }
        return false;
    }

    /**
     * 比较左右运算符优先级,返回状态结果
     * 
     * @param leftOperator
     * @param rightOperator
     * @return
     */
    int compareOperatorNice(char left, char right) {
        if (leftOperator.get(left) == rightOperator.get(right)) {
            return 0;
        }
        if (leftOperator.get(left) < rightOperator.get(right)) {
            return -1;
        }
        return 1;
    }

}
View Code

 

posted @ 2017-10-24 19:54  不爱熬夜的猫  阅读(1566)  评论(0编辑  收藏  举报