普通的計算方式,也叫中綴表達式。計算機識別及正確運用需要耗費大量的資源
如:23+45*2-(8+2)
計算機想要正確計算出此時的結果需要十分復雜,更何況情況十分多變。
逆波蘭式:又叫做后綴表達式,它能去除中綴表達式的括號。十分符合計算機的計算思維,能極大提高效率
表達式不能用字符串進行存儲,因為這將無法分辨,應用集合(ArrayList,LinkedList存儲)
如:23 45 2 * 8 2 + - +
那么中綴表達式是如何變成后綴表達式的呢?原則如下:
1.首先把普通的表達式按照運算符分離出來放在一個集合E中,比如1+2*3 分離后集合里的元素就是 1 + 2 * 3 五個元素
2.再定義一個集合R(最好是字符串類型的集合,免得后面要轉類型),主要是用來存放逆波蘭表達式的,還有定義一個堆棧(存儲運算符用),最后從左到右遍歷集合E
3.遍歷E的規則如下:
3.1如果該元素是數字,直接把它添加到集合R中
3.2否則它肯定是運算符,那么再進行判斷
3.2.1如果該元素是左括號,或者當時棧為空,那么直接入棧
3.2.2如果該元素是右括號,則把棧內的運算符出棧並添加到集合R中,直到遇到第一個左括號結束(左括號也出棧但不添加到R)
3.2.3否則該元素是普通的運算符(也就是+-*/之類的),那么用該運算符和棧內的運算符號比較優先級,如果該運算符的優先級比棧內的運算符
優先級高 或者 棧為空,則直接入棧,否則把棧內的運算符出棧並添加到R中,再判斷下個棧內的運算符優先級,直到遇棧內的運
算符優先級<=該運算符或者棧為空時再把該運算符入棧
3.3整個過程完成后,再把棧內的所有運算符出棧並添加到R中
成功得到后綴表達式,但計算機又是如何通過后綴表達式計算出結果的呢?
這就需要運用到數據結構棧的特點
-
- 把上面的數值依次壓入棧,若遇到運算符,則依次拿出棧頂的兩個元素用該運算符進行運算,把結果在壓入棧
- 直到后綴表達式全部讀完,棧頂的數就是運算結果
上式具體流程就是;
-
- 依次把23 45 2 壓入棧
- 計算45*2=90,90壓入棧
- 依次把8 2 壓入棧
- 計算8+2=10 10壓棧
- 計算90-10=80 80壓入棧
- 計算23+80=103 103壓入棧
- 提取棧頂103
代碼如下;
import java.util.ArrayList; import java.util.ListIterator; import java.util.Scanner; import java.util.Stack; public class test { /** * 將字符串轉換為中序表達式 */ public static ArrayList<String> toZhong(String s){ ArrayList<String> arrayList=new ArrayList();//存貯中綴表達式 for(int i=0;i<s.length();i++){ String str=""; if(s.charAt(i)<48||s.charAt(i)>57){//48:0,57:9 str=str+s.charAt(i); arrayList.add(str); } else{ while(i<s.length()&&s.charAt(i)>=48&&s.charAt(i)<=57){ str=str+s.charAt(i); i++; } arrayList.add(str); i--; } } return arrayList; } --------------------------------------------------------------------------------------- /* * 把中綴表達式轉成逆波蘭式 */ public static ArrayList<String> toNishi(ArrayList<String> list){ ArrayList<String> arr=new ArrayList();//用表存儲逆波蘭式 Stack<String> timeStack=new Stack();//臨時存儲操作符 for(String s:list){ if(s.matches("\\d+")){ arr.add(s); } else if(s.equals("(")){ timeStack.push(s); } else if(s.equals(")")){ while(!(timeStack.peek().equals("("))){ arr.add(timeStack.pop()); } } else{ while(timeStack.size()!=0&&getValue(s)<getValue(timeStack.peek())){ arr.add(timeStack.pop()); } timeStack.push(s); } } while(timeStack.size()!=0){ arr.add(timeStack.pop()); } return arr; } public static int getValue(String ss) { if (ss.equals("+")) { return 1; } else if (ss.equals("-")) { return 1; } else if (ss.equals("*")) { return 2; } else if (ss.equals("\\")) { return 2; } return 0; } ------------------------------------------------------------------------------------------ //計算逆波蘭式結果 public static int jisuan(ArrayList<String> arr){ Stack<Integer> jieguo=new Stack<Integer>(); for(String s:arr){ if(s.matches("\\d+")){ jieguo.push(Integer.parseInt(s)); } else if(jieguo.size()>=2){ Integer a=jieguo.pop(); Integer b=jieguo.pop(); if(s.equals("+")){ jieguo.push(b+a); } else if(s.equals("-")){ jieguo.push(b-a); } else if(s.equals("*")){ jieguo.push(b*a); } else if(s.equals("//")){ jieguo.push(b/a); } } } return jieguo.pop(); }