中綴表達式轉換成后綴表達式
1、概述
可以看到,后綴表達式適合計算式進行運算,但是人卻不太容易寫出來,尤其是表達式很長得情況下,因此在開發中,需要將 中綴表達式轉成后綴表達式。
2、具體步驟
1.初始化兩個棧:運算符棧s1和儲存中間結果的棧s2;
2.從左至右掃描中綴表達式;
3.遇到操作數時,將其壓s2;
4.遇到運算符時,比較其與s1棧頂運算符的優先級:
(1)如果s1為空,或棧頂運算符為左括號“(”,則直接將此運算符入棧;
(2)否則,若優先級比棧頂運算符的高,也將運算符壓入s1;
(3)否則,將s1棧頂的運算符彈出並壓入到s2中,再次轉到(4.1)與s1中新的棧頂運算符相比較;
5.遇到括號時:
(1)如果是左括號"(",則直接壓入s1
(2)如果是右括號")",則依次彈出s1棧頂的運算符,並壓入s2,直到遇到左括號為止,此時將這一對括號丟棄
6.重復步驟2至5,直到表達式的最右邊
7.將s1中剩余的運算符依次彈出並壓入s2
8.依次彈出s2中的元素並輸出,結果的逆序即為中綴表達式對應的后綴表達式
3、案例
將中綴表達式 "1+((2+3)*4)-5" 轉換為后綴表達式的過程如下:
結果為:"1 2 3 + 4 * 5 - "
4、思路分析示意圖
5、代碼實現
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Stack; 4
5 /**
6 * 把中綴表達式轉成后綴表達式 7 * 8 */
9 public class ToSuffixExpression { 10
11 public static void main(String[] args) { 12 // 完成一個中綴表達式轉成 后綴表達式 13 // 說明 14 // 1. 1+((2+3)*4)-5 => 轉成 123 + 4 * + 5- 15 // 2. 因為對 str進行操作不方便,先將 中綴表達式 存入 list 16 // 3.將得到的中綴表達式對應的 list轉成 =>后綴表達式對應的list 17 // 即[1,+,(,(,2,+,3,),*,4,),-,5] => [1,2,3,+,4,*,+,5,-]
18
19 String expression = "1+((2+3)*4)-5"; 20 List<String> list = toInfixExpressionList(expression); 21 System.out.println("中綴表達式對應的list="+list); 22 List<String> list2 = parseSuffixExpressionList(list); 23 System.out.println("后綴表達式對應的list="+list2); 24 } 25
26 //方法:將得到的中綴表達式對應的 list轉成 =>后綴表達式對應的list
27 public static List<String> parseSuffixExpressionList(List<String> ls) { 28 //定義兩個棧
29 Stack<String> s1 = new Stack<String>(); // 符號棧 30
31 //說明:因為 s2這個棧,在整個轉換過程中,沒有pop操作,后面還需要逆序輸出 32 //所以,把 s2 這個棧換成 List<String> 即可 33 //Stack<String> s2 = new Stack<String>(); // 存儲中間結果的棧
34 List<String> s2 = new ArrayList<String>(); //存儲中間結果的list 35
36 //遍歷 ls
37 for(String item : ls) { 38 //如果是一個棧,就加入到s2
39 if(item.matches("\\d+")) { 40 s2.add(item); 41 } else if (item.equals("(")) { 42 s1.push(item); 43 } else if (item.equals(")")) { 44 // 如果是右括號,則依次彈出s1棧頂的運算符,並壓入 s2,知道遇到左括號為止,此時將這一對括號丟棄
45
46 while(!s1.peek().equals("(")) { 47 s2.add(s1.pop()); 48 } 49 s1.pop(); // 將左括號 彈出,消除小括號
50 } else { 51 // 當 item 的優先級小於或等於棧頂運算符,將s1棧頂的運算符彈出並壓入s2中,再次轉到4.1與s1中新的棧頂運算符相比較 52 //問題:缺少比較優先級高低的方法
53 while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)) { 54 s2.add(s1.pop()); 55 } 56 //還需要將 item 壓入 棧中
57 s1.push(item); 58 } 59 } 60
61 //將s1中剩余的運算符依次彈出加入s2
62 while(s1.size()!=0) { 63 s2.add(s1.pop()); 64 } 65
66 return s2; //因為存放到list中,因此,按順序輸出就是對應的后綴表達式對應的 list
67 } 68
69
70 // 方法:將中綴表達式轉成對應的 list
71 public static List<String> toInfixExpressionList(String s) { 72 // 定義一個 list,存放中綴表達式 對應的內容
73 List<String> ls = new ArrayList<String>(); 74 int i = 0; // 指針,用於遍歷中綴表達式字符串
75 String str; // 做對多位數的拼接工作
76 char c; // 每遍歷到一個字符,就放入到 c
77
78 do { 79 // 如果c是一個非數字,就需要加入到 ls
80 if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) { 81 ls.add("" + c); 82 i++; // i后移
83 } else { // 如果是數字,考慮多位數問題
84 str = ""; // 將 str置空
85 while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) { 86 str += c; // 拼接
87 i++; 88 } 89 ls.add(str); 90 } 91
92 } while (i < s.length()); 93 return ls; // 返回
94 } 95 } 96
97 /**
98 * 可以返回一個運算符的對應的優先級 99 * 100 */
101 public class Operation { 102 private static int ADD = 1; 103 private static int SUB = 1; 104 private static int MUL = 2; 105 private static int DIV = 2; 106
107 // 寫一個方法,返回對應的優先級數字
108 public static int getValue(String operation) { 109 int result = 0; 110 switch(operation) { 111 case "+": 112 result = ADD; 113 break; 114 case "-": 115 result = SUB; 116 break; 117 case "*": 118 result = MUL; 119 break; 120 case "/": 121 result = DIV; 122 break; 123 default: 124 System.out.println("不存在該運算符"); 125 break; 126 } 127 return result; 128 } 129 }