逆波兰表达式&后缀表达式

概念

  1. 前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前。比如:- × + 3 4 5 6
  2. 中缀表达式就是常见的运算表达式,如(3+4)×5-6
  3. 后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后,比如:3 4 + 5 × 6 -

人类最熟悉的一种表达式1+2,(1+2)3,3+42+4等都是中缀表示法。对于人们来说,也是最直观的一种求值方式,先算括号里的,然后算乘除,最后算加减,但是,计算机处理中缀表达式却并不方便。

我们先看一个例子 (3+4)× 5 - 6  后缀表达式3 4 + 5 × 6 -的计算

  1. 从左至右扫描,将3和4压入堆栈;
  2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
  3. 将5入栈;
  4. 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
  5. 将6入栈;
  6. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

中缀表达式转换为后缀表达式

1.数字直接入队列
2.运算符要与栈顶元素比较
 ①栈为空直接入栈
 ②运算符优先级大于栈顶元素优先级则直接入栈
 ③小于或等于则出栈入列,再与栈顶元素进行比较,直到运算符优先级小于栈顶元
    素优先级后,操作符再入栈
3.操作符是 ( 则无条件入栈
4.操作符为 ),则依次出栈入列,直到匹配到第一个“(”为止,此操作符直接舍弃,“(”直接出栈舍弃

 

public class SuffixAlgorithm {

    private static char LEFT_BRACKET = Operator.LEFT_BRACKET.value;
    private static char RIGHT_BRACKET = Operator.RIGHT_BRACKET.value;


    private static void rpn(Stack<Character> operators, Stack output, String exp){
        char[] chars = exp.toCharArray();
        int len = chars.length;
        int bracket = 0; // operators中的左括号的数量

        for (int i = 0; i < len; ) {
            int pre = i;//处理开始下标
            boolean digital = Boolean.FALSE; //是否为数字(只要不是运算符,都是数字),用于截取字符串
            while (i < len && !Operator.isOperator(chars[i])) {
                i++;
                digital = Boolean.TRUE;
            }

            if (digital) {//如果是数字,直接压入output
                output.push(exp.substring(pre, i));
            }else{
                char o = chars[i++];

                if (o == LEFT_BRACKET){//左括号直接压入output
                    operators.push(o);
                    bracket++;
                    continue;
                }

                if(o == RIGHT_BRACKET){//是右括号

                    if(bracket < 1){
                        throw new IllegalArgumentException("can't find '('");
                    }
                    //将operators栈顶弹出压入output直到左括号
                    while (!operators.empty()) {
                        char top = operators.pop();
                        if (top == LEFT_BRACKET) {
                            break;
                        }
                        output.push(top);
                    }
                    bracket--;
                    continue;
                }

                char p;
                while (!operators.empty()
                        && ( p = operators.peek()) != LEFT_BRACKET
                        && Operator.cmp(o, p) <= 0){
                    output.push(operators.pop());
                }
                operators.push(o);
            }
        }
        while (!operators.empty()){
            output.push(operators.pop());
        }
    }

    public static void main(String[] args) {
        System.out.println(rpn("a*(b-c*d)+e-f/g*(h+i*j-k)"));
        System.out.println("a,b,c,d,*,-,*,e,+,f,g,/,h,i,j,*,+,k,-,*,-");
    }

    public static String rpn(String exp){
        Stack<Character> operators = new Stack<>();
        Stack<Character> output = new Stack();
        rpn(operators, output, exp);
        String str = "";
        for(int i=0; i<output.size();i++){
           str += String.valueOf(output.get(i));
        }
        return str;
    }

    static enum Operator {
        ADD('+', 1), SUBTRACT('-', 1),
        MULTIPLY('*', 2), DIVIDE('/', 2),
        LEFT_BRACKET('(', 3), RIGHT_BRACKET(')', 3);

        char value;
        int priority;

        Operator(char value, int priority) {
            this.value = value;
            this.priority = priority;
        }

        /**
         * 比较两个符号的优先级
         *
         * @param c1
         * @param c2
         * @return c1的优先级是否比c2的高,高则返回正数,等于返回0,小于返回负数
         */
        public static int cmp(char c1, char c2) {
            int p1 = 0;
            int p2 = 0;
            for (Operator o : Operator.values()) {
                if (o.value == c1) {
                    p1 = o.priority;
                }
                if (o.value == c2) {
                    p2 = o.priority;
                }
            }
            return p1 - p2;
        }

        /**
         * 枚举出来的才视为运算符,用于扩展
         *
         * @param c
         * @return
         */
        public static boolean isOperator(char c) {
            for (Operator o : Operator.values()) {
                if (o.value == c) {
                    return true;
                }
            }
            return false;
        }
        
         public static Operator findOperator(char c){
            for (Operator o : Operator.values()) {
                if (o.value == c) {
                    return o;
                }
            }
            return null;
        }
    }
}


 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值