• 栈的应用 -- 无括号表达式的求值


    package com.learn.algorithm.expression;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Stack;
    
    /**
     * 无括号表达式求值
     * @author Jiekun.Cui
     *
     */
    public class Expression {
        
        
        /**
         * 操作符的优先级定义
         */
        public static Map<String,Integer> optProirity = null;
        static{
            optProirity = new HashMap<>();
            optProirity.put("+", 100);
            optProirity.put("-", 100);
            optProirity.put("*", 200);
            optProirity.put("/", 200);
            optProirity.put("^", 300);//乘幂
            
        }
        
        public static void main(String[] args) throws Exception {
            String s = "11+2-41*6/2+3^3-88";
            
            
            System.out.println(getExpressionValue(s));
        }
    
        private static Number getExpressionValue(String exp) throws Exception {
            Stack<String> optr = new Stack<>(); //运算符栈
            Stack<Number> ovs = new Stack<>(); //运算数栈
            
            StringBuilder sb = new StringBuilder("");
             
            for (int i = 0; i < exp.length(); i++) {
                String t = exp.substring(i, i+1);
                
                if(optProirity.containsKey(t)){
                    
                    ovs.push( Integer.valueOf(sb.toString()) );
                    sb = new StringBuilder("");
                    
                    if ( optr.isEmpty() ) {
                        optr.push(t);
                    } else {
                        
                        //把要进栈的运算符和当店栈顶的运算符进行比较,判断当前是否需要进行运算
                        while ( !(optProirity.get( optr.peek() ) < optProirity.get(t)) ) { 
                            
                            Number n2 = ovs.pop();
                            Number n1 = ovs.pop();
                            
                            ovs.push( calcu(n1, n2, optr.pop()) );
                            
                            if(optr.isEmpty()){
                                break;
                            }
                        }
                        
                        optr.push(t);
                        
                    }
                        
                    
                } else {
                    sb.append(t);
                }
                
            }
            
            
            ovs.push( Integer.valueOf(sb.toString()) );//将最后一个操作数进栈
            
            while ( !optr.isEmpty() ) { //运算符栈不为空则继续进行运算
                Number n2 = ovs.pop();
                Number n1 = ovs.pop();
                ovs.push( calcu(n1, n2, optr.pop()) );
            }
            
            return ovs.peek();
        }
        
        
        public static Number calcu(Number n1,Number n2,String opt) throws Exception{
            
            switch (opt) {
            case "+":
                return n1.intValue() + n2.intValue();
            case "-":
                return n1.intValue() - n2.intValue();
            case "*":
                return n1.intValue() * n2.intValue();
            case "/":
                return n1.intValue() / n2.intValue();
            case "^":
                return ( (Double)Math.pow(n1.intValue(), n2.intValue()) ).intValue();
            default:
                throw new Exception("错误的运算符:" +  opt);
            }
            
        }
        
        
    
    }

    目前只是实现了 Integer 类型的运算 ,也没有对表达式进行验证, 后续有待完善

  • 相关阅读:
    C# 调用Java Webservice 加入SoapHeader 验证信息
    SqlServer查找表中多余的重复记录
    INI文件的读写
    Sql触发器脚本
    Sql遍历更新脚本
    CAS 单点登录,通过ticket 获取登录用户
    模块 | 验证格式
    aja如何解决跨域请求?
    说说各个浏览器box模型
    Vue 双向数据绑定原理分析
  • 原文地址:https://www.cnblogs.com/Jiekun-Cui/p/7367950.html
Copyright © 2020-2023  润新知