后缀表达式 (又称 逆波兰表达式) Java代码的简单实现

表达式求值问题

好久没有发随笔了,最近学习复习数据结构的时候看到了后缀表达式(逆波兰表达式)
发现了栈的精巧,自己想实现一下,本来想用C写的,但是实在太困难了,所有写了个简单的Java版本,还可以的
输入中缀表达式 可以得到计算结果

  • 中缀表达式
  • 后缀表达式 (又称 逆波兰表达式)
  • 前缀表达式(又称 波兰表达式)
中缀表达式 后缀表达式 前缀表达式
a+b ab+ +ab
a+b-c ab+c- -+abc
a+b-c*d ab+cd*- -+ab*cd

利用栈实现输入中缀字符串完成后缀计算

Java代码

由于c代码不好字符串转小数,也不好记录连续的数字,所有采用java实现;这里只涉及+ - * /(加减乘除)

package com.mhy.calculate;

import java.util.ArrayDeque;
import java.util.Deque;

public class Calculate {
    public static void main(String[] args) {
        Calculate calculate = new Calculate();
        String str = "11.2*88.9-(5*8+83.5-99)+55-88/44-(8+2-3+(55*8))-11.18-46+1";
        System.out.println(calculate.calculate(str));
        //521
    }

    public double calculate(String str){
        int nums = 0;//记录数字个数
        int length = str.length();//字符串的长度
        Deque<Double> numQ = new ArrayDeque<>();//数字栈
        Deque<Character> charQ = new ArrayDeque<>();//符号栈

        for (int i = 0; i < length; i++) {
            char x = str.charAt(i);
            if(isNum(x)){//如果x是数或者小数点
                nums++;
            }else {
                if(nums != 0){//数字入栈
                    double v = Double.parseDouble(str.substring(i - nums, i));//截取小数
                    numQ.offerFirst(v);//数字入栈
                }
                nums = 0;//重置记录个数

                if(x == '('){//判断是否为'(',
                    charQ.offerFirst(x);
                    continue;
                }else if(charQ.isEmpty()){//判断是否为空
                    charQ.offerLast(x);
                    continue;
                }

                while(true){//符号栈的弹出操作
                    if(charQ.isEmpty()) {//如果为空了
                        if(x != ')'){//并且这个字符不是')'就入栈
                            charQ.offerFirst(x);
                        }
                        break;//结束循环
                    }
                    char y = charQ.peekFirst();//获取符号的栈顶元素
                    if(y == '(' && x == ')') {//如果栈顶为'(' 且 需要入栈的是')'
                        charQ.pollFirst();//就直接'('弹出栈,')'不入栈
                        break;//结束循环
                    }
                    if(y == '(' && x != ')'){//如果栈顶为'(' 且 需要入栈的不是')'
                        charQ.offerFirst(x);//直接入栈
                        break;//结束循环
                    }
                    if(x == ')'){//如何入栈的是')' 开始弹栈进行运算
                        char p = charQ.pollFirst();//栈顶符号
                        double b = numQ.pollFirst();//后操作数
                        double a = numQ.pollFirst();//前操作数
                        numQ.offerFirst(cal(a,b,p));//结果入栈
                        continue;
                    }

                    if(operatorsRules(x,y)){//如果不是')',就符号比较,大于等于就运算
                        charQ.pollFirst();
                        double b = numQ.pollFirst();
                        double a = numQ.pollFirst();
                        numQ.offerFirst(cal(a,b,y));
                    }else {//否则符号入栈
                        charQ.offerFirst(x);
                        break;
                    }
                }
            }
        }

        if(nums != 0){//数字入栈 由于中缀输入都是以数字结尾,所以最后还需要进行运算
            double v = Double.parseDouble(str.substring(length - nums, length));
            numQ.offerFirst(v);
        }

        while(!charQ.isEmpty()){//把符号栈谈完
            char p = charQ.pollFirst();
            double b = numQ.pollFirst();
            double a = numQ.pollFirst();
            numQ.offerFirst(cal(a,b,p));
        }

        return numQ.pollFirst();//最好数字栈的栈顶就是结果
    }

    //是否为数
    public boolean isNum(char x){
        if(x == '.') return true;
        return x >= 48 && x <= 57;
    }

    //计算
    public Double cal(double a,double b,char x){
        if(x == '*') return a*b;
        if(x == '/') return a/b;
        if(x == '-') return a-b;
        if(x == '+') return  a+b;
        return null;
    }

    //符号优先级判断
    public boolean operatorsRules(char x,char y){
        if(x == '*' || x== '/'){
            if(y == '*') return true;
            else if(y == '/') return true;
            else if(y == '+') return false;
            else if(y == '-') return false;
        }
        if(x == '+' || x == '-'){
            if(y == '-') return true;
            else if(y == '+') return true;
            else if(y == '*') return true;
            else if(y == '/') return true;
        }
        System.out.println("符号输入错误");
        return false;
    }
}
posted @ 2022-10-17 17:26  水三丫  阅读(130)  评论(0编辑  收藏  举报