1. 程式人生 > >逆波蘭表示式原理實現

逆波蘭表示式原理實現

解析原理如下:

(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");