逆波兰计算器

利用逆波兰表达式(后缀表达式),实现简易计算器

实现功能:将中缀表达式转化为后缀表达式,进行基本的加减乘除操作,数字为多位整数,包含括号

实现思路:

1.输入一个逆波兰表达式 (3+4)*5-6 ——> 逆波兰表达式 3 4 + 5 * 6 -
   将中缀表达式转换为逆波兰表达式,输入字符串,从左至右依次判断,
  1.1 定义一个字符串,定义 index ,记录遍历的数字 使用StringBuilder 进行拼接 字符+空格
      遇到数字,继续判断下一个是否为数字,若是,进行字符串拼接。若不是,将遍历的字符串存放在数组中。
  1.2 定义一个符号栈 AuxiliaryStack (辅助栈)
      遇到符号。若栈为空,符号入栈
      若栈不为空,当前符号和栈顶符号进行比较,若当前符号的优先级高于栈顶符号的优先级,入符号栈
      若当前符号的优先级低于等于栈顶符号的优先级,弹出栈顶元素并输出存放在数组中,当前元素继续和新的栈顶元素进行比较
      左括号,直接压入堆栈(括号是最高优先级,无需比较)(入栈后优先级降到最低,确保其他符号正常入栈)
      右括号,(意味着括号已结束)不断弹出栈顶运算符并输出直到遇到左括号(弹出但不输出)
      若遍历完字符串,栈中依旧有元素,将栈中元素依次弹出,存放在数组中
2.计算逆波兰表达式
  2.1 遍历字符串,遇到运算数,数字压入栈  numStack,
  2.2 遇到符号,栈中弹出两个数字,次栈元素 运算符 栈顶元素 ,计算结果存入栈中,继续遍历。最后的结果即为计算结果

代码实现:


import java.util.Stack;

public class CountPalishCalculator {
    // TODO: 2021/9/3
    /**
     * 输入一个逆波兰表达式(后缀表达式),使用栈Stack ,计算出其结果
     */
    private static final int INITSIZE = 10;

    /**
     * 判断输入的字符为操作符还是运算符
     * @param value  输入的字符
     * @return
     */
    public static boolean isSymbol(char value){
        return value == '+' || value == '-' || value == '*' || value == '/' || value =='(' || value == ')';
    }

    /**
     * 根据提供的字符判断其优先级大小,优先级越高,返回值越大
     * @param symbol
     * @return
     */
    public static int priority(char symbol){
        if(symbol == '*' || symbol == '/'){
            return 2;
        }else if(symbol == '+' || symbol == '-'){
            return 1;
        }else if(symbol == '(' ){
            // 入栈 并将优先级降到最低
            return 0;
        }else{
            return -1;   // 输入有误
        }
    }

    /**
     * 加减乘除的计算方式
     * @param num1  栈顶运算值
     * @param num2  次顶运算值
     * @param symbol  操作符
     * @return
     */
    public static float countMethod(float num1, float num2, char symbol){
        float res = 0;
        switch (symbol){
            case('+'):
                res = num1 + num2;
                break;
            case('-'):
                res = num2 - num1;
                break;
            case('*'):
                res = num1 * num2;
                break;
            case('/'):
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }

   
    /**
     *将输入的中缀表达式转化为 后缀表达式 存放在stringBuilder1 中
     * @param str  输入的中缀表达式
     * @return
     */
    public static StringBuilder postfixNotation(String str){
        int index = 0; // 记录遍历的顺序
        char ch = 0; // 用来存放遍历的字符
        StringBuilder stringBuilder1 = new StringBuilder();
        Stack AuxiliaryStack = new Stack();  // 辅助栈
        char symbol = 0; // 表示弹出的栈顶元素
        while(true) {
            ch = str.substring(index, index + 1).charAt(0);// 遍历字符串的字符
            if(isSymbol(ch) == true){ // 字符为符号,入栈

                if(AuxiliaryStack.isEmpty()){  // 若栈为空,则直接入栈
                    AuxiliaryStack.push(ch);
                    index++;
                }else{
                    if(ch == '('){ // 左括号:直接压入堆栈(括号是最高优先级,无需比较)(入栈后优先级降到最低,确保其他符号正常入栈)
                        AuxiliaryStack.push(ch);
                    }else if(ch == ')'){ // 不断弹出栈顶运算符并输出直到遇到左括号(弹出但不输出)
                        while(true){
                            if((char)AuxiliaryStack.peek() == '('){  // 遇到左括号,左括号输入但不弹出
                                AuxiliaryStack.pop();
                                break;
                            }
                            stringBuilder1.append(AuxiliaryStack.pop());  // 未遇到左括号,输出并保存到stringBuilder1中
                            stringBuilder1.append(" ");
                        }
                        index++;
                    }else {
                        // 若栈不为空,当前符号和栈顶符号进行比较,若当前符号的优先级高于栈顶符号的优先级,入符号栈
                        // 若当前符号的优先级低于等于栈顶符号的优先级,弹出栈顶元素并输出存放在数组中,当前元素继续和新的栈顶元素进行比较
                        while (true) {
                            // 判断输出参数是否正确
                            if(priority(ch) < 0 || (!AuxiliaryStack.isEmpty()&&priority((char) AuxiliaryStack.peek())<0)){
                                System.out.println("符号输入错误");
                                break;
                            }
                            // 当前运算符和栈顶元素比较优先级,当栈为空时,当前运算符为唯一的运算符,无法比较,则直接入栈即可
                            if(AuxiliaryStack.isEmpty()){
                                AuxiliaryStack.push(ch);
                                index++;
                                break;
                            }
                            int num1 = priority(ch); // 当前符号的优先级
                            int num2 = priority((char) AuxiliaryStack.peek()); // 当前栈的栈顶元素的优先级,但不弹出
                            if (num1 > num2) {
                                AuxiliaryStack.push(ch);
                                index++;
                                break;
                            } else {
                                symbol = (char) AuxiliaryStack.pop(); //弹出栈顶元素
                                stringBuilder1.append(symbol);
                                stringBuilder1.append(" ");
                            }

                        }

                    }
                }
            }else {   // 字符为数字  ,存入数组中
                // 遇到数字,判断数字是否为最后一个字符,若是,该字符存入数组中;
                // 若不是,继续判断下一个是否为数字,若是,进行字符串拼接。若不是,将遍历的字符串存放在数组中。

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(ch);
                if(index == str.length()-1){  // 判断是否为最后一个字符 ,若是,直接拼接到stringBuilder中
                    stringBuilder1.append(stringBuilder);
                    stringBuilder1.append(" ");
                    index++;
                }else {
                    while (true) {
                        // 第一个字符不是字符串的最后一个字符,通过while循环判断下一个字符是否为数字,
                        // 一直到最后一个字符,也是数字,拼接到stringBUilder中
                        if(index == str.length()-1){
                           stringBuilder1.append(stringBuilder);
                           stringBuilder1.append(" ");
                           index++;
                           break;
                        }
                        // 判断下一个字符是否为数字
                        ch = str.substring(index + 1, index + 2).charAt(0);
                        if (isSymbol(ch) == true) { // 若是符号,直接拼接
                            stringBuilder1.append(stringBuilder);
                            stringBuilder1.append(" ");
                            index++;
                            break;
                        }
                        stringBuilder.append(ch);  // 若不是,继续判断并拼接
                        index++;
                    }

                }
            }
            // 判断字符串是否遍历完,若遍历完,则输出辅助栈中存放的符号,直至栈空
            if(index >= str.length()){
                while (true){
                    if(AuxiliaryStack.isEmpty()){
                        break;
                    }
                    char symbol1 = (char)AuxiliaryStack.pop();
                    stringBuilder1.append(symbol1);
                    stringBuilder1.append(" ");
                }
                break;
            }
        }
        return stringBuilder1;
    }
    //  2.1 遍历字符串,遇到运算数,数字压入栈  numStack,
    //  2.2 遇到符号,栈中弹出两个数字,次栈元素 运算符 栈顶元素 ,计算结果存入栈中,继续遍历。最后的结果即为计算结果

    public static float Method(String str){
        float num1 = 0;  // 栈顶操作数
        float num2 = 0;  // 次顶操作数
        float result = 0;
        Stack numStack = new Stack();
        // 遍历字符串
        for(int i = 0;i<str.length();i++){
            if(isSymbol(str.charAt(i)) == false && str.charAt(i) != ' '){ // 不是符号也不是空格,为数字
                StringBuilder Keep = new StringBuilder();
                Keep.append(str.charAt(i));
                int count = i;
                // 遍历当前字符串的下一个字符
                for(int j = count+1;j<str.length();j++){
                    if(isSymbol(str.charAt(j)) == false && str.charAt(j) != ' ') {  // 为数字
                        Keep.append(str.charAt(j));
                        i++;
                    }else{
                        break;
                    }
                }
                String s = Keep.toString();  //  StringBuilder转化为String类型
                numStack.push(Float.parseFloat(s));  // String类型转化为float类型
            }else if(str.charAt(i) ==' '){  // 是空格
                continue;
            }else if (isSymbol(str.charAt(i))){  // 若为符号,进行加减乘除基本操作
                if(numStack.peek() instanceof Float){
                    num1 =  (Float) numStack.pop();
                    num2 = (Float) numStack.pop();
                }
                char symbol = str.charAt(i);
                result = countMethod(num1,num2,symbol);
                numStack.push(result);
            }
        }
        return result;
    }
    public static void main(String[] args) {
        String str = "(3+40)*5-62";
        StringBuilder s1 = postfixNotation(str);
        String s = s1.toString();
        float res1 = Method(s);
        System.out.println("(3+40)*5-62 = "+res1);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值