Java实现中缀表达式转后缀表达式并计算结果

中缀表达式就是形如a(b-c)+d*这样我们平常写的式子,如果按平时逻辑上的处理顺序的话计算机比较难正确处理,因为运算符之间有优先级,括号的优先级比乘除高,乘除的优先级比加减高,这是小学的知识。
如果利用栈的先进后出(First In Last Out)的特性,可以将中缀表达式转为后缀表达式。
后缀表达式不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *

思路

  1. 读入字符
  2. 如果读入的字符为操作符,则压栈,如果是操作数,则输出
  3. 如果读入的 操作符优先级比栈顶元素低,则弹出栈操作符直至遇到比读入的操作符优先级更低的操作符。左括号( 为特殊情况,读入时当作高优先级,弹出时为低优先级,直至读入一个) 右括号,然后弹出栈中第一个左括号及其之前的所有操作符
根据后缀表达式计算结果

当见到一个数时就把它推入栈中,在遇到一个操作符时该操作符就作用于从该栈弹出的两个操作数上,再将所得的结果推出栈中。

public class Postfix {
    //用于记录操作符
    private static LinkedList<String> operators=new LinkedList<>();
    //用于记录输出
    private static LinkedList<String> output=new LinkedList<>();
    //用于展示后缀表达式
    private static StringBuilder sb=new StringBuilder();

    public static void main(String[] args) {
        LinkedList<String> list=new LinkedList<>();
        Scanner scanner=new Scanner(System.in);
        String s;
        //#号结束输入,输入的字符间要有空格,方便处理
        while (!(s=scanner.next()).equals("#")) {
            list.add(s);
        }
        transferToPostfix(list);
        scanner.close();
    }

    //中缀表达式转为后缀表达式
    private static void transferToPostfix(LinkedList<String> list){
        Iterator<String> it=list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if (isOperator(s)) {
                if (operators.isEmpty()) {
                    operators.push(s);
                }
                else {
                    //如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样,则将操作符压入栈
                    if (priority(operators.peek())<=priority(s)&&!s.equals(")")) {
                        operators.push(s);
                    }
                    else if(!s.equals(")")&&priority(operators.peek())>priority(s)){
                        while (operators.size()!=0&&priority(operators.peek())>=priority(s)
                                &&!operators.peek().equals("(")) {
                            if (!operators.peek().equals("(")) {
                                String operator=operators.pop();
                                sb.append(operator).append(" ");
                                output.push(operator);
                            }
                        }
                        operators.push(s);
                    }
                    //如果读入的操作符是")",则弹出从栈顶开始第一个"("及其之前的所有操作符
                    else if (s.equals(")")) {
                        while (!operators.peek().equals("(")) {
                            String operator=operators.pop();
                            sb.append(operator).append(" ");
                            output.push(operator);
                        }
                        //弹出"("
                        operators.pop();
                    }
                }
            }
            //读入的为非操作符
            else {
                sb.append(s).append(" ");
                output.push(s);
            }
        }
        if (!operators.isEmpty()) {
            Iterator<String> iterator=operators.iterator();
            while (iterator.hasNext()) {
                String operator=iterator.next();
                sb.append(operator).append(" ");
                output.push(operator);
                iterator.remove();
            }
        }
        System.out.println("后缀: "+sb);
        calculate();
        //Collections.reverse(output);
    }

    //根据后缀表达式计算结果
    private static void calculate(){
        LinkedList<String> mList=new LinkedList<>();
        String[] postStr=sb.toString().split(" ");
        for (String s:postStr) {
            if (isOperator(s)){
                if (!mList.isEmpty()){
                    int num1=Integer.valueOf(mList.pop());
                    int num2=Integer.valueOf(mList.pop());
                    if (s.equals("/")&&num1==0){
                        System.out.println("除数不能为0");
                        return;
                    }
                    int newNum=cal(num2,num1,s);
                    mList.push(String.valueOf(newNum));
                }
            }
            else {
                //数字则压入栈中
                mList.push(s);
            }
        }
        if (!mList.isEmpty()){
            System.out.println("result: "+mList.pop());
        }
    }

    //判断是否操作符
    private static boolean isOperator(String oper){
        if (oper.equals("+")||oper.equals("-")||oper.equals("/")||oper.equals("*")
                ||oper.equals("(")||oper.equals(")")) {
            return true;
        }
        return false;
    }
    //计算操作符的优先级
    private static int priority(String s){
        switch (s) {
            case "+":return 1;
            case "-":return 1;
            case "*":return 2;
            case "/":return 2;
            case "(":return 3;
            case ")":return 3;
            default :return 0;
        }
    }

    private static int cal(int num1,int num2,String operator){
        switch (operator){
            case "+":return num1+num2;
            case "-":return num1-num2;
            case "*":return num1*num2;
            case "/":return num1/num2;
            default :return 0;
        }
    }

}

结果

6 * ( 5 + ( 2 + 3 ) * 8 + 3 )
#
后缀: 6 5 2 3 + 8 * + 3 + * 
result: 288
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值