逆波兰表达式原理实现

解析原理如下:

(1) 该运算符为左括号"(",则直接存入运算符堆栈。
      (2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止,此时抛弃该左括号。
      (3) 该运算符为非括号运算符:
      (a) 若运算符堆栈栈顶的运算符为左括号,则直接存入运算符堆栈。
      (b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
      (c) 若比运算符堆栈栈顶的运算符优先级低或相等,则输出栈顶运算符到操作数堆栈,直至运算符栈栈顶运算符低于(不包括等于)该运算符优先级,或为左括号,
           并将当前运算符压入运算符堆栈。


具体实现:

package com.example.admin.myapplication;

import android.os.Build;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

/**
 * Created by admin on 2017/11/8.
 * 逆波兰算法实现
 * 仅支持 + - * /
 */

public class NBLArithmetic {
    private enum Operator {
        ADD("+", 1),
        SUBJECT("-", 1),
        RIDE("*", 2),
        DIVIDE("/", 2),
        BRACKET_L("(", 0),
        BRACKET_R(")", 0),;

        Operator(String value, int weight) {
            this.value = value;
            this.weight = weight;
        }

        String value;
        int weight;

        public String getValue() {
            return value;
        }

        public int getWeight() {
            return weight;
        }

        static Operator fromValue(String value) {
            Operator[] values = values();
            for (Operator val : values) {
                if (value.equals(val.getValue())) {
                    return val;
                }
            }
            return null;

        }

    }

    /**
     * 运算符栈
     */
    private Stack<Operator> operatorStack;
    /**
     * 操作数栈
     */
    private Stack<Integer> operandStack;
    /**
     * 临时存储区,存放逆波兰运算中间结果
     */
    private LinkedList<String> cacheQueue;

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
    public NBLArithmetic() {
        operatorStack = new Stack<>();
        operandStack = new Stack<>();
        cacheQueue = new LinkedList<>();
    }

    /**
     * 计算结果
     *
     * @param operation
     */
    public void opera(String operation) {
        List<String> operas = getArrayFormOperation(operation);
        for (String opera : operas) {
            if (TextUtils.isDigitsOnly(opera)) {
                cacheQueue.add(opera);
            } else {
                Operator operator = Operator.fromValue(opera);
                Operator lastOperator = operatorStack.empty() ? null : operatorStack.peek();
                if (lastOperator == null || lastOperator == Operator.BRACKET_L || operator == Operator.BRACKET_L) {
                    operatorStack.push(operator);
                } else {
                    switch (operator) {
                        case ADD:
                        case RIDE:
                        case DIVIDE:
                        case SUBJECT:
                            while (lastOperator != null && operator.getWeight() <= lastOperator.getWeight()) {//栈顶优先级大于等于本次操作符
                                cacheQueue.add(operatorStack.pop().getValue());
                                lastOperator = operatorStack.empty() ? null : operatorStack.peek();
                            }
                            operatorStack.push(operator);
                            break;
                        case BRACKET_R:
                            while (lastOperator != null && lastOperator != Operator.BRACKET_L) {
                                cacheQueue.add(operatorStack.pop().getValue());
                                lastOperator = operatorStack.empty() ? null : operatorStack.peek();
                            }
                            operatorStack.pop();
                            break;
                    }
                }
            }
        }
        while (!operatorStack.isEmpty()) {
            cacheQueue.add(operatorStack.pop().getValue());
        }


        //-----------------------开始计算---------------------------------------------------

        while (cacheQueue.size() > 0) {
            String data = cacheQueue.removeFirst();
            if (TextUtils.isDigitsOnly(data)) {
                operandStack.push(Integer.parseInt(data));
            } else {
                Operator operator = Operator.fromValue(data);
                int b = operandStack.pop();
                int a = operandStack.pop();
                switch (operator) {
                    case ADD:
                        operandStack.push(a + b);
                        break;
                    case RIDE:
                        operandStack.push(a * b);
                        break;
                    case DIVIDE:
                        operandStack.push(a / b);
                        break;
                    case SUBJECT:
                        operandStack.push(a - b);
                        break;
                }
            }
        }

        Log.i("NBL", operation + " = " + operandStack.pop());
    }

    /**
     * 解析表达式成array
     *
     * @param operation
     * @return
     */
    private List getArrayFormOperation(String operation) {
        List operaList = new ArrayList();
        char[] chars = operation.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (char a : chars) {
            if (TextUtils.isDigitsOnly(a + "")) {
                sb.append(a + "");
            } else if (".".equals(a + "")) {
                sb.append(a + "");
            } else {
                if (sb.length() > 0) {
                    operaList.add(sb.toString());
                }
                operaList.add(a + "");
                sb.delete(0, sb.length());
            }
        }
        if (sb.length() > 0) {
            operaList.add(sb.toString());
        }
        return operaList;
    }

}
 
 
使用很方便:
new NBLArithmetic().opera("3+4*(3-5)*2");
new NBLArithmetic().opera("3+4*(3-5)*2+56");
new NBLArithmetic().opera("3+4*(3-5)*2+56-3*2");
new NBLArithmetic().opera("3+4*(3-5)*2+56-3*2+(2-8)*4");
new NBLArithmetic().opera("56-3+(2-8)*4");
new NBLArithmetic().opera("3+4*(3-5)*2+56-3*2+(2-8)*4");

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值