逆波兰表达式的思考与JAVA实现

最近在研究一个配置解析相关功能, 解析是针对一些规则进行, 考虑到规则的多样性,准备采用逆波兰表达式来进行拆解,然后再单独进行原子化处理。

上面说的规则其实就是一个公式,公式可以分为两部分:

  • 运算量
  • 运算符

运算量比较号理解, 就是A+B+C公式里的ABC,运算符相对复杂一些,对于数学四则运算来说就是+、-、*、/ ,其实如果拓展一下, 运算符可以是现有的逻辑运算符号比如:&、|、!、^ 等,也可以自定义一个特殊含义的运算符,比如说 = 代表两边都需要成立,>代表左边成立,右边也需要成立,<代表右边成立,左边也都成立,这是从运算符自生属性上来解释。不过运算符还需要考虑它们的作用范围,我大概将其分为三类:

  • ( ) 括号类的, 作用域为前后对于的一组为范围
  • 单元组范围:该类运算符只需要一个运算量就可以参与运算
  • 二元组范围:该类运算符需要两个运算量参与才能进一步运算
  • 三元及多元组:这类我暂时没有想明白

下面是一个对逆波兰表达式的JAVA实现代码,需要注意的是:

  • 仅仅支持单字符运算符与小括号(不支持中括号、大括号)
  • 可以自定义符号的优先级
  • 刚刚出土的代码, 所以性能问题及bug来了不要怕

计划,针对该逆波兰表达式,再封装对其的运算量及运算符的操作,这个以后再更新。

package rule;

import java.util.*;

/**
 * 逆波兰表达式生成的array deque
 * <li><b>仅仅支持单字符运算符与小括号(不支持中括号、大括号)</b></li>
 * <li>可以自定义符号的优先级</li>
 *
 * @author 54117
 */
public class RPN {

    Queue<String> rpn = new ArrayDeque<>();

    public static HashMap<String, Integer> prioritizedOps = new LinkedHashMap<>(16);

    static {
        prioritizedOps.put("(", 1000);
        prioritizedOps.put(")", 1000);

        prioritizedOps.put("!", 1);
        prioritizedOps.put("^", 2);
        prioritizedOps.put("&", 3);
        prioritizedOps.put("|", 4);
        //        prioritizedOps.put("=>", 5);
        //        prioritizedOps.put("<=", 6);
        //        prioritizedOps.put("<=>", 7);
        prioritizedOps.put("*", 10);
        prioritizedOps.put("/", 10);
        prioritizedOps.put("+", 20);
        prioritizedOps.put("-", 20);

    }

    public static RPN rpn(String rule) {
        if (null == rule || "".equals(rule)) {
            return null;
        }
        RPN re = new RPN();
        Queue<String> rpn = re.rpn;

        Stack<String> optStack = new Stack<>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rule.length(); i++) {
            String s = String.valueOf(rule.charAt(i));
            boolean isOpt = prioritizedOps.containsKey(s);
            if (isOpt) {
                //
                if (sb.length() > 0) {
                    String preV = sb.toString();
                    sb.delete(0, sb.length());
                    rpn.offer(preV);
                }
                if ("(".equals(s)) {
                    optStack.push(s);
                } else if (")".equals(s)) {
                    while (!optStack.isEmpty()) {
                        String ss = optStack.pop();
                        if ("(".equals(ss)) {
                            break;
                        }
                        rpn.offer(ss);
                    }
                } else {
                    // 比较
                    Integer optP = prioritizedOps.getOrDefault(s, 10000);
                    if (!optStack.isEmpty()) {
                        //判断是否在比较的过程中入栈
                        boolean pushed = false;
                        while (!optStack.isEmpty()) {
                            Integer lstP = prioritizedOps.getOrDefault(optStack.peek(), 10000);
                            // 优先级高,则入栈
                            if (optP < lstP) {
                                optStack.push(s);
                                pushed = true;
                                break;
                            } else {
                                //否则退栈输出
                                rpn.offer(optStack.pop());
                            }
                        }
                        if (!pushed) {
                            optStack.push(s);
                        }
                    } else {
                        //栈为空,直接入栈
                        optStack.push(s);
                    }
                }
            } else {
                sb.append(s);
            }
        }
        if (sb.length() > 0) {
            String preV = sb.toString();
            rpn.offer(preV);
        }
        while (!optStack.isEmpty()) {
            rpn.offer(optStack.pop());
        }
        return re;
    }

    @Override
    public String toString() {
        return rpn.toString();
    }

	// test 
	public static void main(String[] args) {
        // [A, B, +, C, D, -, *]
        System.out.println( RPN.rpn("((A+B))*(C-D)").toString());
        // [A, B, +, C, *, D, -]
        System.out.println( RPN.rpn("((A+B))*C-D").toString());
        // [A, B, +, C, *, D, -]
        System.out.println( RPN.rpn("(((A+B))*C)-D").toString());
        // [A, !, B, C, &, |]
        System.out.println( RPN.rpn("!A|B&C").toString());
        //[A, B, !, |, C, |, D, E, ^, |]
        System.out.println( RPN.rpn("A|!B|C|D^E").toString());
    }
}

参考百度百科关于逆波兰表达式的流程图
逆波兰表达式

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值