Java 学习笔记---逆波兰表达式

3 篇文章 0 订阅
3 篇文章 0 订阅

以下是个人根据逆波兰式的算法写的java程序,如有错误或者意见,欢迎留言或者其他方式。

import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

public class Generator {

    /**
     * 定义运算符优先级
     * 
     * @param operator
     * @return int 优先级的数字
     */
    public static int getPriority(String operator) {
        final int plusPriority = 2;
        final int multiplyPriority = 3;

        if ("+".equals(operator))
            return plusPriority;

        if ("-".equals(operator))
            return plusPriority;

        if ("*".equals(operator))
            return multiplyPriority;

        if ("/".equals(operator))
            return multiplyPriority;

        if ("%".equals(operator))
            return multiplyPriority;

        return 0;
    }

    /**
     * 中序表达转逆序表达
     * 
     * @param str
     */
    public Stack<String> cal(String str) {

        Stack<String> s1 = new Stack<String>();// 逆波兰式
        Stack<String> s2 = new Stack<String>();// 临时空栈

        // 分割字符,运算数,运算符
        String[] ch1 = split(str);

        // 表达式转换
        for (int i = 0; i < ch1.length; i++) {

            String c = ch1[i];
            // (1)如果遇到的是数字,我们直接加入到栈S1中;
            if (isNumber(c)) {
                s1.push(c);
                continue;
            }

            // (2)如果遇到的是左括号,则直接将该左括号加入到栈S2中;
            if (c.equals("(")) {
                s2.push(c);
                continue;
            }

            if (c.equals(")") && s2.isEmpty()) {
                new Exception();
            }

            // (3)如果遇到的是右括号,那么将栈S2中的运算符一次出栈加入到栈S1中,直到遇到左括号,但是该左括号出栈S2并不加入到栈S1中
            if (c.equals(")")) {
                String temp = (String) s2.pop();

                while (!temp.equals("(")) {
                    if (temp.isEmpty())
                        new Exception();
                    s1.push(temp);
                    temp = (String) s2.pop();
                }
                continue;
            }

            // (4)如果遇到的是运算符,包括单目运算符和双目运算符 :
            // 4.1 如果栈s2为空,则直接将运算符加入栈s2
            if (s2.isEmpty()) {
                s2.push(c);
                continue;
            }

            /**
             * (2)如果此时栈S2不为空,当前遍历的运算符的优先级大于等于栈顶运算符的优先级,那么直接入栈S2;
             */
            if (!isHight((String) s2.peek(), c)) {

                s2.push(c);
                continue;
            } else {
                // (3)如果此时栈S2不为空,当前遍历的运算符的优先级小于栈顶运算符的优先级,则将栈顶运算符一直出栈加入到栈S1中,
                // 直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,此时将该运算符加入到栈S2中;
                String temp = (String) s2.pop();
                while (true) {
                    s1.push(temp);
                    if (s2.isEmpty()) {
                        s2.push(c);
                        break;
                    }
                    if (!isHight(temp, c)) {
                        s2.push(c);
                        break;
                    }
                    temp = (String) s2.pop();
                }
                continue;
            }

        }

        // (5)栈S2中仍然存在运算符,那么将这些运算符依次出栈加入到栈S1中,直到栈为空。
        while (!s2.isEmpty()) {
            s1.push(s2.pop());
        }
        return s1;
    }

    // 分割字符串
    private String[] split(String src) {
        StringBuilder sb = new StringBuilder(src.length());
        for (char ch : src.toCharArray()) {
            if (isOperator(String.valueOf(ch))) {
                sb.append("," + ch + ",");
            } else {
                sb.append(ch);
            }
        }
        String string = sb.toString().replaceAll(",+", ",");
        return string.split(",");
    }

    /**
     * 判断字符是否是数字
     * 
     * @param str
     * @return boolean
     */
    public boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("^[0-9a-zA-Z]*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 判断字符是否是运算符
     * 
     * @param str
     * @return boolean
     */
    public boolean isOperator(String str) {
        Pattern pattern = Pattern.compile("^[\\+\\-\\*\\/\\%\\(\\)\\{\\}\\[\\]]");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 比较字符串优先级
     * 
     * @param str
     * @param str2
     * @return
     */
    private boolean isHight(String str, String str2) {
        return getPriority(str) > getPriority(str2);
    }

    public double getRes(String str) {
        Stack<String> s = cal(str);
        Stack<Double> res = new Stack<Double>();
        for (String string : s) {
            if (isNumber(string)) {
                res.push(Double.valueOf(string.toString()));
            } else {
                Double x = res.pop();
                Double y = res.pop();
                switch (string) {
                case "+":
                    res.push(x + y);
                    break;
                case "-":
                    res.push(y - x);
                    break;
                case "*":
                    res.push(y * x);
                    break;
                case "/":
                    if (x != 0)
                        res.push(y - x);
                    else {
                        new Exception();
                    }
                    break;
                case "%":
                    if (x != 0)
                        res.push(y % x);
                    else {
                        new Exception();
                    }

                }
            }
        }
        Double result = res.pop();
        res.clear();
        return result;
    }

    @Test
    public void test() {
    System.err.println("569+365*(24+60)-1993%9+11/8=" + getRes("569+365*(24+60)-1993%9+11/8"));

    }
}

运算的结果:

569+365*(24+60)-1993%9+11/8=31228.0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值