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

Posted 观堂村程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈的应用 -- 无括号表达式的求值相关的知识,希望对你有一定的参考价值。

 

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++:算术表达式求值

Dijkstra的双栈算术表达式的求值算法

栈的典型应用-表达式求值

Stack实现表达式的求值

王道3.3 栈的应用

中缀表达式转换成后缀表达式并求值