基本概念
逆波蘭式(ReversePolishnotation,RPN,或逆波蘭記法),也叫字尾表示式(將運算子寫在運算元之後)。
中序表示式就是我們數學中常見的算式形式。
舉例說明
中序表示式:3+4*5-6
轉化成逆波蘭式:3 4 5 * + 6 -
演算法思想
首先建立兩個棧,一個資料棧OPDN,一個操作符棧OPTR。
先將“#”棧底標誌放到操作符棧。
從中序表示式pre的第一個字元讀起:
1.如果pre[i]是運算元,就直接入資料棧;
2.如果pre[i]為左括號,就壓入操作符棧;
3.如果pre[i]為右括號,就將操作符棧中的運算子一次出棧並依次壓入資料棧,一直到操作符棧頂元素為左括號停止,但是這個時候要將左括號出棧,而且不壓入資料棧;
4.如果pre[i]為操作符:
a.如果操作符棧為空,就將操作符pre[i]壓入資料棧;
b.如果pre[i]的優先順序大於操作符棧頂元素的優先順序,就將此pre[i]壓入資料棧;
c.如果操作符棧不為空而且pre[i]的優先順序小於等於操作符棧頂元素的優先順序,就將操作符棧中的元素依次出棧並且壓入資料棧,指導不滿足上述條件,將此操作符pre[i]壓入資料棧。
5.如果遍歷完整個中序的表示式,操作符棧還存有運算子,就將全部運算子出棧並且壓入資料棧,直到為空。
6.最後將整個資料棧的元素依次壓入操作符棧,然後正序輸出操作符棧就可以得到逆波蘭式了。
利用棧將中序表示式轉換成逆波蘭式程式碼表達
建立computer類和Mycounter主類
class computer
類方法 | 說明 |
public int randomnum() | 返回一個隨機數 |
public String symbol() | 返回+-*/中的一個隨機符號 |
public boolean isNum(String pre) | 判斷中序表示式中的字元是否為數字 |
public boolean isoperator(String sym) | 判斷中序表示式中的字元是否為“+,-,*,/”符號中的一種 |
public int priority(String sym) | 返回每種符號的優先順序表示數 |
void toback(String pre[]) | 將輸入的pre[]轉換成逆波蘭式後輸出 |
1 package Mycounter; 2 import java.lang.Math; 3 import java.util.Stack; 4 import java.util.regex.Matcher; 5 import java.util.regex.Pattern; 6 public class computer { 7 //生成0-100的隨機數 8 public int randomnum() { 9 int random = (int)(Math.random()*10);//Math.random的範圍是[0.0-1.0] 10 return random; 11 12 } 13 //生成一個隨機符號 14 public String symbol(){ 15 16 int i=0; 17 switch(i=(int) (Math.random() * 4)) 18 { 19 case 0: 20 return "+"; 21 case 1: 22 return "-"; 23 case 2: 24 return "*"; 25 case 3: 26 return "/"; 27 default : 28 return null; 29 } 30 31 } 32 //判斷是否為數字 33 public boolean isNum(String pre){ 34 Pattern pattern = Pattern.compile("[0-9]*"); //通過正規表示式判斷String型別是否為數字 35 Matcher isNum = pattern.matcher(pre); 36 if( !isNum.matches() ){ 37 return false; 38 } 39 return true; 40 } 41 //判斷時否為符號 42 public boolean isoperator(String sym){ 43 switch(sym) 44 { 45 case "+": 46 return true; 47 case "-": 48 return true; 49 case "*": 50 return true; 51 case "/": 52 return true; 53 default : 54 return false; 55 } 56 } 57 //判斷符號優先順序,#為棧底標誌 58 public int priority(String sym){ 59 switch(sym) 60 { 61 case "#": 62 return -1; 63 case "(": 64 return 0; 65 case "+": 66 return 1; 67 case "-": 68 return 1; 69 case "*": 70 return 2; 71 case "/": 72 return 2; 73 default : 74 return -1; 75 } 76 } 77 //中綴表示式轉化字首表示式 78 void toback(String pre[]){ 79 80 String bottom="#"; 81 Stack<String> OPTR = new Stack(); //運算子棧 82 Stack<String> OPND = new Stack(); //資料棧 83 84 OPTR.push(bottom); // 首先把結束標誌‘#’放入棧底 85 86 for(int k=0;k<pre.length;k++) 87 { 88 if(isNum(pre[k])) // 遇到數直接寫入字尾表示式 89 { 90 OPND.push(pre[k]); 91 } 92 else if (pre[k]=="(") // 遇到“(”不用比較直接入棧 93 OPTR.push(pre[k]); 94 else if(pre[k] ==")") // 遇到右括號將其對應左括號後的操作符(操作符棧中的)全部寫入字尾表示式 95 { 96 while(OPTR.peek()!="(") 97 { 98 OPND.push( OPTR.peek()); 99 OPTR.pop(); 100 } 101 OPTR.pop(); // 將“(”出棧,字尾表示式中不含小括號 102 } 103 else if (isoperator(pre[k])) 104 { 105 while(!OPTR.empty() && priority(pre[k]) <= priority(OPTR.peek())) 106 { 107 // 當前的操作符小於等於棧頂操作符的優先順序時,將棧頂操作符寫入到字尾表示式,重複此過程 108 OPND.push(OPTR.peek()); 109 OPTR.pop(); 110 } 111 OPTR.push(pre[k]);// 當前操作符棧為空或者當前操作符優先順序大於棧頂操作符的優先順序,將該操作符入棧 112 } 113 114 } 115 while(OPTR.peek() != "#") // 將所有的操作符加入字尾表示式 116 { 117 OPND.push(OPTR.peek()); 118 OPTR.pop(); 119 } 120 OPTR.pop(); 121 122 //利用操作符棧逆序即可得到字尾表示式 123 while(!OPND.empty()) 124 { 125 OPTR.push(OPND.peek()); 126 OPND.pop(); 127 } 128 while(!OPTR.empty()) 129 { 130 System.out.print(OPTR.peek()+" "); 131 OPTR.pop(); 132 } 133 134 } 135 }
Mycounter
主類控制
1 package Mycounter; 2 3 import java.util.Scanner; 4 5 import Mycounter.computer; 6 public class Mycounter { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 computer yl = new computer(); 11 int y1=yl.randomnum();//隨機數y1,y2,y3,y4 12 int y2=yl.randomnum(); 13 int y3=yl.randomnum(); 14 int y4=yl.randomnum(); 15 String sym1=yl.symbol();//隨機操作符sym1,sym2,sym3 16 String sym2=yl.symbol(); 17 String sym3=yl.symbol(); 18 19 String[] zhongshi={String.valueOf(y1),sym1,String.valueOf(y2),sym2,String.valueOf(y3),sym3,String.valueOf(y4)} ;//按中序表示式順序存入String[] 20 for(int i=0;i<zhongshi.length;i++){ //輸出中序表示式 21 System.out.print(zhongshi[i]); 22 23 } 24 System.out.println(""); 25 yl.toback(zhongshi); //轉換成逆波蘭式 26 } 27 28 }
鳴謝
感謝http://blog.csdn.net/axiqia/article/details/50538878#逆波蘭表示式中序表示式轉後序表式式 博主的寫出這麼詳盡的演算法解讀和程式碼演示
程式碼
https:https://git.coding.net/YangXiaomoo/fourcount.git
ssh:git@git.coding.net:YangXiaomoo/fourcount.git
git:git://git.coding.net/YangXiaomoo/fourcount.git