逆波兰问题&计算器实现_学习记录

本文介绍了一种实现逆波兰表达式解析和计算的方法,包括如何将中序表达式转换为逆波兰表达式,以及如何对逆波兰表达式进行求值。提供了详细的算法步骤和Java实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逆波兰问题

package p19;

import java.util.ArrayList;
import java.util.List;

/**
 * 逆波兰表达式求值
 * @author Guozhu Zhu
 * @date 2018/8/5
 * @version 1.0
 *
 */
public class NBL {
	
    private static MyStack ms1 = new MyStack();//生成逆波兰表达式的栈
    private static MyStack ms2 = new MyStack();//运算栈

    // 将字符串转换为中序表达式
    public static List<String> zb(String s) {
        List<String> ls = new ArrayList<String>();//存储中序表达式
        int i = 0;
        String str;
        char c;
        while (i < s.length()){
            if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {
                ls.add("" + c);
                i++;
            } else {
                str = "";
                while (i < s.length() && (c = s.charAt(i)) >= 48
                        && (c = s.charAt(i)) <= 57) {
                    str += c;
                    i++;
                }
                ls.add(str);
            }
        }
        return ls;
    }
    
    //将中序表达式转换为逆波兰表达式
    /**
	1、从左至右扫描中缀表达式。
	2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
	3、若读取的是运算符
	  (1) 该运算符为左括号"(",则直接存入运算符堆栈。
	  (2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
	  (3) 该运算符为非括号运算符:
	      (a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
	      (b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
	      (c) 若比运算符堆栈栈顶的运算符优先级低或相等,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
	4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
     */
    public static List<String> parse(List<String> ls) {
        List<String> lss = new ArrayList<String>();
        for (String ss : ls) {
            if (ss.matches("\\d+") || (ss.charAt(0) == '-' && ss.length() > 1)) {        //数字
                lss.add(ss);
            } else if (ss.equals("(")) {     //(
                ms1.push(ss);
            } else if (ss.equals(")")) {     //)
                while (!ms1.top.equals("(")) {
                    lss.add(ms1.pop());
                }
                ms1.pop();       
            } else {
                while (ms1.size() != 0 && getValue(ms1.top) >= getValue(ss)) {
                    lss.add(ms1.pop());
                }
                ms1.push(ss);
            }
        }
        while (ms1.size() != 0) {
            lss.add(ms1.pop());
        }
        return lss;
    }
    
    //对逆波兰表达式进行求值
    public static int jisuan(List<String> ls) {
        for (String s : ls) {
        	//自然数和负数时
            if (s.matches("\\d+") || (s.length() > 1 && s.charAt(0) == 0)) { 
                ms2.push(s);
            } else {
                int b = Integer.parseInt(ms2.pop());
                int a = Integer.parseInt(ms2.pop());
                if (s.equals("+")) {
                    a = a + b;
                } else if (s.equals("-")) {
                    a = a - b;
                } else if (s.equals("*")) {
                    a = a * b;
                } else if (s.equals("\\")) {
                    a = a / b;
                }
                ms2.push("" + a);
            }
        }
        return Integer.parseInt(ms2.pop());
    }
    
    //获取运算符优先级 +,-为1 *,/为2 ()为0
    public static int getValue(String s) {
        if (s.equals("+")) {
        	return 1;
        } else if (s.equals("-")) {
        	return 1;
        } else if (s.equals("*")) {
        	return 2;
        } else if (s.equals("\\")) {
        	return 2;
        }
        return 0;
    }
    
    //========Test========
    public static void main(String[] args) {
        System.out.println(jisuan(parse(zb("1+((2+3)*4)-5"))));
    }

}
package cn.zhuguozhu.zgzfinal;

import java.math.BigDecimal;
import java.util.ArrayDeque;

public class Calculator {
	
    // 计算表达式的值
    public String caculate(String string) throws Exception {
        // 该部分用来验证中缀表达式是否合理
        // 若右括号数量大于左括号,则说明表达式不合理,抛出异常
        // 否则说明正常,继续进行运算
        int x = 0;
        for (int i = 0; i < string.length(); i++) {
            if (string.charAt(i) == '(') {
                x++;
            } else if (string.charAt(i) == ')') {
                x--;
            }
        }
        if (x < 0) {
            throw new Exception("错误,右括号数量大于左括号");
        }
        // 该集合用来存储操作数
        ArrayDeque<String> value = new ArrayDeque<>();
        // 该集合用来存储运算符
        ArrayDeque<String> operation = new ArrayDeque<>();
        // 该字符串用来临时存储转化后的后缀表达式
        StringBuilder stringBuilder = new StringBuilder();
        // 将中缀表达式的操作数和运算符分离并存放到字符串数组中
        String[] expression = formatInput(string);
        // 遍历字符串数组
        for (String s : expression) {
            // 若该字符串为空则跳过
            if (s.equals(" ") || s.length() == 0) {
                continue;
            } else if (s.charAt(0) == '-' && !s.equals("-")) {    // 若为是负数,则添加至后缀表达式末尾,并补上空格,方便后面将后缀表达式分离
                stringBuilder.append(s + " ");
            } else if (isDigital(s.charAt(0))) {    // 若为正数,添加至后缀表达式并补空格
                stringBuilder.append(s + " ");
            } else if (isOperater(s.charAt(0)) || s.charAt(0) == '(' || s.charAt(0) == ')') {    // 若为运算符,继续判断
                if (s.equals("(")) {//  若为左括号,则压入运算符栈中
                    operation.push(s);
                    continue;
                }
                // 若为右括号,则将运算符栈中第一个左括号以上全部弹出并添加至后缀表达式,左括号直接弹出,不用添加至后缀表达式
                if (s.equals(")")) {
                    while (!operation.getFirst().equals("(")) {
                        if (!operation.getFirst().equals("(")) {
                            stringBuilder.append(operation.poll() + " ");
                        }
                    }
                    if (operation.getFirst().equals("(")) {
                        operation.pop();
                        continue;
                    }
                }
                // 若运算符栈为空,则将运算符压入栈中
                if (operation.isEmpty()) {
                    operation.push(s);
                    continue;
                } else if (priorityIsBiggerOrTheSame(s, operation.getFirst())) {    // 若该运算符比栈顶运算符优先级高,则压入栈中
                    operation.push(s);
                    continue;
                } else {    // 否则弹出所有优先级不比它低的运算符并添加至后缀表达式
                    while (!operation.isEmpty() && !priorityIsBiggerOrTheSame(s, operation.getFirst())) {
                        stringBuilder.append(operation.poll() +" ");
                    }
                    operation.push(s);
                    continue;
                }
            }
        }
        // 弹出操作数栈中所有元素并添加至后缀表达式
        while (!operation.isEmpty()) {
            stringBuilder.append(operation.poll());
        }
        // 格式化后缀表达式(将操作数与运算符分离)
        expression = formatInfixExpression(stringBuilder.toString());
        // 清空后缀表达式
        stringBuilder.delete(0, stringBuilder.length());
        // 遍历字符串数组
        for (String s : expression) {
            // 若该字符串为空,则跳过
            if (s.equals(" ") || s.length() == 0) {
                continue;
            } else if (isDigital(s.charAt(0))) {    // 若为正数则压入操作数栈中
                value.push(s);
            } else if (s.charAt(0) == '-' && !s.equals("-")) {    // 若为负数,则压入操作数栈中
                value.push(s);
            } else if (isOperater(s.charAt(0))) {    // 若为运算符,则判断操作数个数大于2个,则进行弹出两个操作数进行操作,然后将结果压入操作数栈中
                if (value.size() >= 2) {
                    BigDecimal last = new BigDecimal(value.poll());
                    BigDecimal last_p = new BigDecimal(value.poll());
                    if (s.equals("-")) {
                        value.push(last_p.subtract(last).toString());
                    } else if (s.equals("+")) {
                        value.push(last_p.add(last).toString());
                    } else if (s.equals("*")) {
                        value.push(last_p.multiply(last).toString());
                    } else if (s.equals("/")) {
                        value.push(last_p.divide(last, 15, BigDecimal.ROUND_HALF_DOWN).toString());
                    }
                }
            }
        }
        // 弹出最终运算结果并返回
        return value.poll();
    }
    // 判断是否为运算符,若为运算符,则返回true,否则返回false
    public static boolean isOperater(int a) {
        if (a == '+' || a == '-' || a == '*' || a == '/')
            return true;
        return false;
    }
    // 判断是否为数字,若为数字,则返回true,否则返回false
    public static boolean isDigital(int a) {
        if (a >= '0' && a <= '9')
            return true;
        return false;
    }

    // 格式化中缀表达式输入,即在符号前后添加空格,便于后面的分隔操作
    public static String[] formatInput(String s) {
        String temp = "";
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (i == 0 && c == '-') {
                temp += c;
            } else if (isOperater(c) || c == '(' || c == ')') {
                if ((i - 1) >= 0 && (i + 1) < s.length()
                        && (isOperater(s.charAt(i - 1)) || s.charAt(i - 1) == '(' || s.charAt(i - 1) == ' ')
                        && c == '-' && isDigital(s.charAt(i + 1))) {
                    temp += " " + c;
                } else {
                    temp += " " + c + " ";
                }
            } else
                temp += c; // 数字不用加空格
        }
        return temp.split(" "); // 分割
    }
	
    // 格式化后缀表达式
    public static String[] formatInfixExpression(String s) {
        String temp = "";
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (isOperater(c)) {
                if (c == '-' && i + 1 < s.length() && isDigital(s.charAt(i + 1))) {
                    temp += " " + c;
                } else {
                    temp += " " + c + " ";
                }
            } else {
                temp += c; // 数字不用加空格
            }
        }
        return temp.split(" "); // 分割
    }

    // 优先级判断,a是否大于b
    public static boolean priorityIsBiggerOrTheSame(String a, String b) {
        String s = " +- */";
        return s.indexOf(a) - s.indexOf(b) >= 2;
    }
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值