算法:
中綴表達式轉后綴表達式的方法:
1.遇到操作數:直接輸出(添加到后綴表達式中)
2.棧為空時,遇到運算符,直接入棧
3.遇到左括號:將其入棧
4.遇到右括號:執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出。
5.遇到其他運算符:加減乘除:彈出所有優先級大於或者等於該運算符的棧頂元素【棧內的棧頂運算符>=遇到的運算符,就彈出】,然后將該運算符入棧
6.最終將棧中的元素依次出棧,輸出。
例如:【5+4*6/2+3+(4*5)/5】 =24
轉化之后的后綴表達式:【5 4 6 * 2 / + 3 + 4 5 *5 / +】
下面使用java實現 中綴表達式轉化后綴表達式。 【支持多位數字,支持小數,支持+-*/()運算符】
1 package com.agen.exchangePox; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 import java.util.stream.Collectors; 9 10 import org.junit.Test; 11 12 public class InfixInToSuffix { 13 /** 14 *提前將 符號的優先級定義好 15 */ 16 private static final Map<Character, Integer> basic = new HashMap<Character, Integer>(); 17 static { 18 basic.put('-', 1); 19 basic.put('+', 1); 20 basic.put('*', 2); 21 basic.put('/', 2); 22 basic.put('(', 0);//在運算中 ()的優先級最高,但是此處因程序中需要 故設置為0 23 } 24 25 @Test 26 public void test(){ 27 String a = toSuffix("55.6+4*60/2+33+(4.7*5.6)/5");//傳入 一串 算數公式 28 System.out.println(a); 29 System.out.println(dealEquation(a)); 30 31 32 } 33 34 /** 35 * 將 中綴表達式 轉化為 后綴表達式 36 */ 37 public String toSuffix(String infix){ 38 List<String> queue = new ArrayList<String>(); //定義隊列 用於存儲 數字 以及最后的 后綴表達式 39 List<Character> stack = new ArrayList<Character>(); //定義棧 用於存儲 運算符 最后stack中會被 彈空 40 41 char[] charArr = infix.trim().toCharArray(); //字符數組 用於拆分數字或符號 42 String standard = "*/+-()"; //判定標准 將表達式中會出現的運算符寫出來 43 char ch = '&'; //在循環中用來保存 字符數組的當前循環變量的 這里僅僅是初始化一個值 沒有意義 44 int len = 0; //用於記錄字符長度 【例如100*2,則記錄的len為3 到時候截取字符串的前三位就是數字】 45 for (int i = 0; i < charArr.length; i++) { //開始迭代 46 47 ch = charArr[i]; //保存當前迭代變量 48 if(Character.isDigit(ch)) { //如果當前變量為 數字 49 len++; 50 }else if(Character.isLetter(ch)) { //如果當前變量為 字母 51 len++; 52 }else if(ch == '.'){ //如果當前變量為 . 會出現在小數里面 53 len++; 54 }else if(Character.isSpaceChar(ch)) { //如果當前變量為 空格 支持表達式中有空格出現 55 if(len > 0) { //若為空格 代表 一段結束 ,就可以往隊列中 存入了 【例如100 * 2 100后面有空格 就可以將空格之前的存入隊列了】 56 queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); //往 隊列存入 截取的 字符串 57 len = 0; //長度置空 58 } 59 continue; //如果空格出現,則一段結束 跳出本次循環 60 }else if(standard.indexOf(ch) != -1) { //如果是上面標准中的 任意一個符號 61 if(len > 0) { //長度也有 62 queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); //說明符號之前的可以截取下來做數字 63 len = 0; //長度置空 64 } 65 if(ch == '(') { //如果是左括號 66 stack.add(ch); //將左括號 放入棧中 67 continue; //跳出本次循環 繼續找下一個位置 68 } 69 if (!stack.isEmpty()) { //如果棧不為empty 70 int size = stack.size() - 1; //獲取棧的大小-1 即代表棧最后一個元素的下標 71 boolean flag = false; //設置標志位 72 while (size >= 0 && ch == ')' && stack.get(size) != '(') { //若當前ch為右括號,則 棧里元素從棧頂一直彈出,直到彈出到 左括號 73 queue.add(String.valueOf(stack.remove(size))); //注意此處條件:ch並未入棧,所以並未插入隊列中;同樣直到找到左括號的時候,循環結束了,所以左括號也不會放入隊列中【也就是:后綴表達式中不會出現括號】 74 size--; //size-- 保證下標永遠在棧最后一個元素【棧中概念:指針永遠指在棧頂元素】 75 flag = true; //設置標志位為true 表明一直在取()中的元素 76 } 77 while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) { //若取得不是()內的元素,並且當前棧頂元素的優先級>=對比元素 那就出棧插入隊列 78 queue.add(String.valueOf(stack.remove(size))); //同樣 此處也是remove()方法,既能得到要獲取的元素,也能將棧中元素移除掉 79 size--; 80 } 81 } 82 if(ch != ')') { //若當前元素不是右括號 83 stack.add(ch); //就要保證這個符號 入棧 84 } else { //否則就要出棧 棧內符號 85 stack.remove(stack.size() - 1); 86 } 87 } 88 if(i == charArr.length - 1) { //如果已經走到了 中綴表達式的最后一位 89 if(len > 0) { //如果len>0 就截取數字 90 queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1))); 91 } 92 int size = stack.size() - 1; //size表示棧內最后一個元素下標 93 while (size >= 0) { //一直將棧內 符號全部出棧 並且加入隊列中 【最終的后綴表達式是存放在隊列中的,而棧內最后會被彈空】 94 queue.add(String.valueOf(stack.remove(size))); 95 size--; 96 } 97 } 98 99 } 100 return queue.stream().collect(Collectors.joining(",")); //將隊列中元素以,分割 返回字符串 101 } 102 103 104 /** 105 * 將 后綴表達式 進行 運算 計算出結果 106 * @param equation 107 * @return 108 */ 109 public String dealEquation(String equation){ 110 String [] arr = equation.split(","); //根據, 拆分字符串 111 List<String> list = new ArrayList<String>(); //用於計算時 存儲運算過程的集合【例如list中當前放置 100 20 5 / 則取出20/5 最終將結果4存入list 此時list中結果為 100 4 】 112 113 114 for (int i = 0; i < arr.length; i++) { //此處就是上面說的運算過程, 因為list.remove的緣故,所以取出最后一個數個最后兩個數 都是size-2 115 int size = list.size(); 116 switch (arr[i]) { 117 case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(a)); break; 118 case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(b)); break; 119 case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(c)); break; 120 case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(d)); break; 121 default: list.add(arr[i]); break; //如果是數字 直接放進list中 122 } 123 } 124 125 return list.size() == 1 ? list.get(0) : "運算失敗" ; //最終list中僅有一個結果,否則就是算錯了 126 } 127 128 129 130 }
其中的解釋比較詳細,不再贅述!!!
具體示例過程如下: