前言:本篇文章講解如何利用棧,完成一個簡單的算術表達式的計算過程。為了簡單起見,首先假設操作數是整數,而運算符為四種類型:+、-、*、/
-
基本思路:為了完成算術表達式的計算,用到了兩個棧,一個用於存放操作數,另一個用於存放操作符。
- 假設:程序中定義了兩個棧:operandStack(用來存放操作數)、operatorStack(用於存放操作符)。
- 在處理操作數和操作符之前,首先將它們壓入棧中。當要處理一個操作符時,從operatorStack中將它彈出,然后將它應用在來自operandStack的前兩個操作數上,得到的結果再壓入operandStack中。
-
實現的詳細步驟:
-
掃描階段:程序從左到右掃描表達式,提取操作數、運算符和括號。
- 如果提取的字符是一個操作數,將它壓入operandStack中。
- 如果提取的字符是一個+或-的運算符,因為+、-運算符在算術表達式中的優先級是最低的,所以此時在將+或者-運算符插入棧中之前,可以處理operatorStack棧頂的所有運算符,最后將提取出來的運算符壓入operatorStack中。
- 如果提取的字符是一個*或/的運算符,則處理operatorStack棧頂的所有*和/的運算符,最后將新提取出來的運算符壓入operatorStack中。
- 如果提取出來的運算符是一個"(",則將它壓入operatorStack中。
- 如果提取出來的運算符是一個")",則重復處理operatorStack棧頂的運算符,直到看到棧頂的運算符為")"。
- 清除棧階段:重復處理來自operatorStack棧頂的運算符,直到operatorStack為空為止。
- 代碼實現:
- public static int evaluateExpression(String expression){
- Stack<Integer> operandStack = new Stack<Integer>(); //存放操作數的棧
- Stack<Character> operatorStack = new Stack<Character>();//存放運算符的棧
-
- String[] charArr = expression.split(""); //將字符串分割成單個字符
- for(int i = 0; i < charArr.length; i++){
- if(charArr[i].trim().equals("")){ //如果字符串為空,則跳過此次循環
- continue;
- }else if(charArr[i].trim().equals("+") || charArr[i].trim().equals("-")){
- //如果字符串為"+"或者"-",則執行棧中已存數據的加減乘除計算
- while(!operatorStack.isEmpty() &&
- (operatorStack.peek() == '+' ||
- operatorStack.peek() == '-' ||
- operatorStack.peek() == '*' ||
- operatorStack.peek() == '/')){
- processOneOperator(operandStack,operatorStack);
- }
- operatorStack.push(charArr[i].charAt(0));//將操作符壓入操作符棧中
- }else if(charArr[i].trim().equals("*") || charArr[i].trim().equals("/")){
- //如果字符串為"*"或者"/",則執行棧中已存數據的乘除計算
- while(!operatorStack.isEmpty() &&
- (operatorStack.peek() == '*' ||
- operatorStack.peek() == '/')){
- processOneOperator(operandStack, operatorStack);
- }
- operatorStack.push(charArr[i].charAt(0));
- }else if(charArr[i].trim().equals("(")){
- //如果遇到左括號,則將左括號壓入操作符棧中
- operatorStack.push('(');
- }else if(charArr[i].trim().equals(")")){
- //如果遇到右括號,則計算棧中的數據,直到遇到左括號為止
- while(operatorStack.peek() != '('){
- processOneOperator(operandStack,operatorStack);
- }
- operatorStack.pop();//將進行過計算的左括號彈出
- }else{
- //如果遇到的是操作數,則將操作數直接壓入操作數棧中
- operandStack.push(Integer.parseInt(charArr[i]));
- }
- }
- //對棧中數據進行計算,知道棧為空為止
- while(!operatorStack.isEmpty()){
- processOneOperator(operandStack,operatorStack);
- }
- //此時操作數棧中的棧頂元素也就是計算結果
- return operandStack.pop();
- }
-
- /**
- * 對操作符棧頂的一個操作符進行計算
- * @param operandStack
- * @param operatorStack
- */
- public static void processOneOperator(Stack<Integer> operandStack,Stack<Character> operatorStack){
- char op = operatorStack.pop(); //取操作符的棧頂元素
- int op1 = operandStack.pop(); //取操作數的棧頂元素
- int op2 = operandStack.pop(); //取操作數的棧頂元素
- if(op == '+'){ //如果操作數為+,則執行兩個操作數的求和操作,並將結果壓入操作數棧中
- operandStack.push(op2 + op1);
- }else if(op == '-'){
- operandStack.push(op2 - op1);
- }else if(op == '*'){
- operandStack.push(op2 * op1);
- }else if(op == '/'){
- operandStack.push(op2 / op1);
- }
- }
|
4.測試代碼:
public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("7+(1+1)*2 = " + evaluateExpression("7+(1+1)*2")); } |
顯示結果: