數據結構Java實現06----中綴表達式轉換為后綴表達式


本文主要內容:

  • 表達式的三種形式
  • 中綴表達式與后綴表達式轉換算法

一、表達式的三種形式:

  • 中綴表達式:運算符放在兩個運算對象中間,如:(2+1)*3。我們從小做數學題時,一直使用的就是中綴表達式。
  • 后綴表達式:不包含括號,運算符放在兩個運算對象的后面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則),如:2 1 + 3 *。又比如3+(6-4/2)*5=23的后綴表達式為:3642/-5*+# (#符號為結束符)
  • 前綴表達式:同后綴表達式一樣,不包含括號,運算符放在兩個運算對象的前面,如:* + 2 1 3 。前綴表達式和后綴表達式其實是差不多的,只不過符號位置不同而已,前綴表達式不是很常見。

 

二、中綴表達式轉換為后綴表達式:(思路)

1、將中綴表達式轉換為后綴表達式:(步驟,有點難理解)

(1)當讀到數字直接送至輸出隊列中;

(2)當讀到運算符t時:

  a.將棧中所有優先級高於或等於t的運算符彈出,送到輸出隊列中;

    注:這句話不好理解,可以說成這樣,從棧頂開始,依次彈出比當前處理的運算符優先級高的運算符,直到一個比它優先級低的或者遇到了一個左括號就停止

  b.t進棧;

(3)讀到左括號時總是將它壓入棧中;

(4)讀到右括號時,將靠近棧頂的第一個左括號上面的運算符全部依次彈出,送至輸出隊列后,再丟棄左括號;

(5)中綴表達式全部讀完后,若棧中仍有運算符,將其送到輸出隊列中。

 

舉例:

124b3dd7-f3b3-4110-904c-8a2b1d85dccd

上圖中,左側的那一列為輸出序列,右側的那一列為棧。

2、運用后綴表達式進行計算:

  (1)建立一個棧S;

  (2)從左到右讀后綴表達式,讀到數字就將它轉換為數值壓入棧S中,讀到運算符則從棧中依次彈出兩個數分別到Y和X,然后以“X 運算符 Y”的形式計算機出結果,再壓加棧S中;

  (3)如果后綴表達式未讀完,就重復上面過程,最后輸出棧頂的數值則為結束。

舉例:

3+(2-5)*6/3=-3 ,其后綴表達式為:325-6*3/+。其運算結果如下:

45270e43-7c61-4ac2-af8f-efb437e8d742

三、代碼實現:將中綴表達式轉換為后綴表達式

  • JDK  Stack類使用
  • 使用泛型

代碼實現:

(1)StringToArithmetic.java:(中綴表達式轉化為后綴表達式的工具類

  1 /**
  2  * Created by smyhvae on 2015/9/7.
  3  * 工具類:
  4  * 1、中綴表達式轉化為后綴表達式
  5  * 2、給出一個算術表達式(中綴表達式),直接得到計算結果
  6  */
  7 
  8 import java.util.Stack;
  9 import java.util.regex.Pattern;
 10 
 11 public class StringToArithmetic {
 12 
 13     private StringToArithmetic() {
 14     }
 15 
 16     //方法:給出一個算術表達式(中綴表達式),得到計算結果。 例如 (5+8+10)*1,返回23
 17     public static double stringToArithmetic(String string) {
 18         return suffixToArithmetic(infixToSuffix(string));
 19     }
 20 
 21     /**
 22      * 中綴表達式轉后綴表達式 只處理了+,-,*,/和括號,沒有處理負號及其它運算符,也沒對前綴表達式驗證。
 23      * 如要處理負號,可對表達式進行預轉義處理,當下面條件成立時,將負號換成單目運算符"!" infix.charAt[i]=='-'&&(
 24      * i==0||infix.charAt[i-1]=='(')
 25      * 3*6/4+3
 26      * 3+6-4           3 6 + 4 -
 27      * 3+(6-4/2)*5    3 6 4 2 / - 5 * +
 28      */
 29     //方法:中綴表達式轉成后綴表達式
 30     public static String infixToSuffix(String infix) {
 31         Stack<Character> stack = new Stack<Character>();
 32         String suffix = "";
 33         int length = infix.length();
 34         for (int i = 0; i < length; i++) {
 35             Character temp;
 36             char c = infix.charAt(i);
 37             switch (c) {
 38                 // 忽略空格
 39                 case ' ':
 40                     break;
 41                 // 碰到'(',push到棧
 42                 case '(':
 43                     stack.push(c);
 44                     break;
 45                 // 碰到'+''-',將棧中所有運算符彈出,送到輸出隊列中
 46                 case '+':
 47                 case '-':
 48                     while (stack.size() != 0) {
 49                         temp = stack.pop();
 50                         if (temp == '(') {
 51                             stack.push('(');
 52                             break;
 53                         }
 54                         suffix += " " + temp;
 55                     }
 56                     stack.push(c);
 57                     suffix += " ";
 58                     break;
 59                 // 碰到'*''/',將棧中所有乘除運算符彈出,送到輸出隊列中
 60                 case '*':
 61                 case '/':
 62                     while (stack.size() != 0) {
 63                         temp = stack.pop();
 64                         if (temp == '(' || temp == '+' || temp == '-') {
 65                             stack.push(temp);
 66                             break;
 67                         } else {
 68                             suffix += " " + temp;
 69                         }
 70                     }
 71                     stack.push(c);
 72                     suffix += " ";
 73                     break;
 74                 // 碰到右括號,將靠近棧頂的第一個左括號上面的運算符全部依次彈出,送至輸出隊列后,再丟棄左括號
 75                 case ')':
 76                     while (stack.size() != 0) {
 77                         temp = stack.pop();
 78                         if (temp == '(')
 79                             break;
 80                         else
 81                             suffix += " " + temp;
 82                     }
 83                     // suffix += " ";
 84                     break;
 85                 //如果是數字,直接送至輸出序列
 86                 default:
 87                     suffix += c;
 88             }
 89         }
 90 
 91         //如果棧不為空,把剩余的運算符依次彈出,送至輸出序列。
 92         while (stack.size() != 0) {
 93             suffix += " " + stack.pop();
 94         }
 95         return suffix;
 96     }
 97 
 98 
 99     /**
100      * postfix
101      *
102      * @return double
103      */
104     //方法:通過后綴表達式求出算術結果
105     public static double suffixToArithmetic(String postfix) {
106 
107         Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)"); //使用正則表達式 匹配數字
108         String strings[] = postfix.split(" ");  //將字符串轉化為字符串數組
109         for (int i = 0; i < strings.length; i++)
110             strings[i].trim();  //去掉字符串首尾的空格
111         Stack<Double> stack = new Stack<Double>();
112 
113         for (int i = 0; i < strings.length; i++) {
114 
115             if (strings[i].equals(""))
116                 continue;
117 
118             //如果是數字,則進棧
119             if ((pattern.matcher(strings[i])).matches()) {
120 
121                 stack.push(Double.parseDouble(strings[i]));
122             } else {
123                 //如果是運算符,彈出運算數,計算結果。
124                 double y = stack.pop();
125                 double x = stack.pop();
126                 stack.push(caculate(x, y, strings[i])); //將運算結果重新壓入棧。
127             }
128         }
129         return stack.pop(); //彈出棧頂元素就是運算最終結果。
130 
131     }
132 
133     private static double caculate(double x, double y, String simble) {
134         if (simble.trim().equals("+"))
135             return x + y;
136         if (simble.trim().equals("-"))
137             return x - y;
138         if (simble.trim().equals("*"))
139             return x * y;
140         if (simble.trim().equals("/"))
141             return x / y;
142         return 0;
143     }
144 }

(2)Test.java:(測試類)

 1 public class Test {
 2     public static void main(String[] args) {
 3 
 4         String str = "3+(2-5)*6/3";  //其后綴表達式為325-6*3/+
 5 
 6         //調用方法:中綴表達式轉成后綴表達式
 7         System.out.println(StringToArithmetic.infixToSuffix(str));
 8 
 9         //調用方法:給出一個算術表達式(中綴表達式),得到計算結果
10         System.out.println(StringToArithmetic.stringToArithmetic(str));
11 
12     }
13 
14 }

上方代碼中,第07行是根據中綴表達式算出后綴表達式。

第10行:是給出一個中綴表達式,直接的到計算結果,其實它的步驟是:先根據中綴表達式得到后綴表達式,然后根據后綴表達式去計算結果

運行效果:

68bb3685-b736-4d3b-95ad-6a6981b80071

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM