




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、前綴、中綴、后綴表達式它們都是對表達式的記法,因此也被稱為前綴記法、中綴記法和后綴記法。它們之間的區別在于運算符相對與操作數的位置不同:前綴表達式的運算符位于與其相關的操作數之前;中綴和后綴同理。舉例:(3 + 4) × 5 - 6 就是中綴表達式- × + 3 4 5 6 前綴表達式3 4 + 5 × 6 - 后綴表達式中綴表達式(中綴記法)中綴表達式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處于操作數的中間。中綴表達式是人們常用的算術表示方法。雖然人的大腦很容易理解與分析中綴表達式,但對計算機來說中綴表達式卻是很復雜的,因此計算表
2、達式的值時,通常需要先將中綴表達式轉換為前綴或后綴表達式,然后再進行求值。對計算機來說,計算前綴或后綴表達式的值非常簡單。前綴表達式(前綴記法、波蘭式)前綴表達式的運算符位于操作數之前。前綴表達式的計算機求值:從右至左掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(棧頂元素 op 次頂元素),并將結果入棧;重復上述過程直到表達式最左端,最后運算得出的值即為表達式的結果。例如前綴表達式“- × + 3 4 5 6”:(1) 從右至左掃描,將6、5、4、3壓入堆棧;(2) 遇到+運算符,因此彈出3和4(3為棧頂元素,4為次頂元素,注意與
3、后綴表達式做比較),計算出3+4的值,得7,再將7入棧;(3) 接下來是×運算符,因此彈出7和5,計算出7×5=35,將35入棧;(4) 最后是-運算符,計算出35-6的值,即29,由此得出最終結果。可以看出,用計算機計算前綴表達式的值是很容易的。將中綴表達式轉換為前綴表達式:遵循以下步驟:(1) 初始化兩個棧:運算符棧S1和儲存中間結果的棧S2;(2) 從右至左掃描中綴表達式;(3) 遇到操作數時,將其壓入S2;(4) 遇到運算符時,比較其與S1棧頂運算符的優先級:(4-1) 如果S1為空,或棧頂運算符為右括號“)”,則直接將此運算符入棧;(4-2) 否則,若優先級比棧頂
4、運算符的較高或相等,也將運算符壓入S1;(4-3) 否則,將S1棧頂的運算符彈出并壓入到S2中,再次轉到(4-1)與S1中新的棧頂運算符相比較;(5) 遇到括號時:(5-1) 如果是右括號“)”,則直接壓入S1;(5-2) 如果是左括號“(”,則依次彈出S1棧頂的運算符,并壓入S2,直到遇到右括號為止,此時將這一對括號丟棄;(6) 重復步驟(2)至(5),直到表達式的最左邊;(7) 將S1中剩余的運算符依次彈出并壓入S2;(8) 依次彈出S2中的元素并輸出,結果即為中綴表達式對應的前綴表達式。例如,將中綴表達式“1+(2+3)×4)-5”轉換為前綴表達式的過程如下:掃描到的元素S2(
5、棧底->棧頂)S1 (棧底->棧頂)說明55空數字,直接入棧-5-S1為空,運算符直接入棧)5- )右括號直接入棧45 4- )數字直接入棧×5 4- ) ×S1棧頂是右括號,直接入棧)5 4- ) × )右括號直接入棧35 4 3- ) × )數字+5 4 3- ) × ) +S1棧頂是右括號,直接入棧25 4 3 2- ) × ) +數字(5 4 3 2 +- ) ×左括號,彈出運算符直至遇到右括號(5 4 3 2 + ×-同上+5 4 3 2 + ×- +優先級與-相同,入棧15 4 3
6、 2 + × 1- +數字到達最左端5 4 3 2 + × 1 + -空S1中剩余的運算符因此結果為“- + 1 × + 2 3 4 5”。后綴表達式(后綴記法、逆波蘭式)后綴表達式與前綴表達式類似,只是運算符位于操作數之后。后綴表達式的計算機求值:與前綴表達式類似,只是順序是從左至右:從左至右掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(次頂元素 op 棧頂元素),并將結果入棧;重復上述過程直到表達式最右端,最后運算得出的值即為表達式的結果。例如后綴表達式“3 4 + 5 × 6 -”:(
7、1) 從左至右掃描,將3和4壓入堆棧;(2) 遇到+運算符,因此彈出4和3(4為棧頂元素,3為次頂元素,注意與前綴表達式做比較),計算出3+4的值,得7,再將7入棧;(3) 將5入棧;(4) 接下來是×運算符,因此彈出5和7,計算出7×5=35,將35入棧;(5) 將6入棧;(6) 最后是-運算符,計算出35-6的值,即29,由此得出最終結果。將中綴表達式轉換為后綴表達式:與轉換為前綴表達式相似,遵循以下步驟:(1) 初始化兩個棧:運算符棧S1和儲存中間結果的棧S2;(2) 從左至右掃描中綴表達式;(3) 遇到操作數時,將其壓入S2;(4) 遇到運算符時,比較其與
8、S1棧頂運算符的優先級:(4-1) 如果S1為空,或棧頂運算符為左括號“(”,則直接將此運算符入棧;(4-2) 否則,若優先級比棧頂運算符的高,也將運算符壓入S1(注意轉換為前綴表達式時是優先級較高或相同,而這里則不包括相同的情況);(4-3) 否則,將S1棧頂的運算符彈出并壓入到S2中,再次轉到(4-1)與S1中新的棧頂運算符相比較;(5) 遇到括號時:(5-1) 如果是左括號“(”,則直接壓入S1;(5-2) 如果是右括號“)”,則依次彈出S1棧頂的運算符,并壓入S2,直到遇到左括號為止,此時將這一對括號丟棄;(6) 重復步驟(2)至(5),直到表達式的最右邊;(7) 將S1中剩余的運算符
9、依次彈出并壓入S2;(8) 依次彈出S2中的元素并輸出,結果的逆序即為中綴表達式對應的后綴表達式(轉換為前綴表達式時不用逆序)。例如,將中綴表達式“1+(2+3)×4)-5”轉換為后綴表達式的過程如下:掃描到的元素S2(棧底->棧頂)S1 (棧底->棧頂)說明11空數字,直接入棧+1+S1為空,運算符直接入棧(1+ (左括號,直接入棧(1+ ( (同上21 2+ ( (數字+1 2+ ( ( +S1棧頂為左括號,運算符直接入棧31 2 3+ ( ( +數字)1 2 3 + (右括號,彈出運算符直至遇到左括號×1 2 3 + ( ×S1棧頂為左括號,運算
10、符直接入棧41 2 3 + 4+ ( ×數字)1 2 3 + 4 ×+右括號,彈出運算符直至遇到左括號-1 2 3 + 4 × +-與+優先級相同,因此彈出+,再壓入-51 2 3 + 4 × + 5-數字到達最右端1 2 3 + 4 × + 5 -空S1中剩余的運算符因此結果為“1 2 3 + 4 × + 5 -”(注意需要逆序輸出)。編寫Java程序將一個中綴表達式轉換為前綴表達式和后綴表達式,并計算表達式的值。其中的toPolishNotation()方法將中綴表達式轉換為前綴表達式(波蘭式)、toReversePolishNo
11、tation()方法則用于將中綴表達式轉換為后綴表達式(逆波蘭式):注:(1) 程序很長且注釋比較少,但如果將上面的理論內容弄懂之后再將程序編譯并運行起來,還是比較容易理解的。有耐心的話可以研究一下。(2) 此程序是筆者為了說明上述概念而編寫,僅做了簡單的測試,不保證其中沒有Bug,因此不要將其用于除研究之外的其他場合。java view plain copy1. package qmk.simple_test; 2. import java.util.Scanner; 3. import java.
12、util.Stack; 4. /* 5. * Example of converting an infix-expression to 6. * Polish Notation (PN) or Reverse Polish Notation (RPN). 7. * Written in 2011-8-25 8. *
13、160;author QiaoMingkui 9. */ 10. public class Calculator 11. public static final String USAGE = "= usage =n" 12.
14、 + "input the expressions, and then the program " 13. + "will calculate them and show the re
15、sult.n" 14. + "input 'bye' to exit.n" 15. /* 16. * param args 17.
16、 */ 18. public static void main(String args) 19. System.out.println(USAGE); 20.
17、; Scanner scanner = new Scanner(System.in); 21. String input = "" 22.
18、160; final String CLOSE_MARK = "bye" 23. System.out.println("input an expression:"); 24.
19、160; input = scanner.nextLine(); 25. while (input.length() != 0 26.
20、 && !CLOSE_MARK.equals(input) 27. System.out.print("Polish Notation (PN):"); 28.
21、60; try 29. toPolishNotation(input); 30.
22、0; catch (NumberFormatException e) 31. &
23、#160; System.out.println("ninput error, not a number."); 32. catch (IllegalArgumentException e) 33. &
24、#160; System.out.println("ninput error:" + e.getMessage(); 34.
25、0; catch (Exception e) 35. System.out.println("ninput error, invalid
26、;expression."); 36. 37. System.out.print("Reverse
27、160;Polish Notation (RPN):"); 38. try 39.
28、; toReversePolishNotation(input); 40. catch (NumberFormatException e) 41.
29、60; System.out.println("ninput error, not a number."); 42.
30、60; catch (IllegalArgumentException e) 43. System.out.println("ninput error:" + e.getMessage(
31、); 44. catch (Exception e) 45.
32、60; System.out.println("ninput error, invalid expression."); 46. 47.
33、0; System.out.println("input a new expression:"); 48. input = scanner.nextLine();
34、49. 50. System.out.println("program exits"); 51. 52.
35、; /* 53. * parse the expression , and calculate it. 54. * param input 55. * throws Ille
36、galArgumentException 56. * throws NumberFormatException 57. */ 58. private static void toPolishNotation(String input)
37、59. throws IllegalArgumentException, NumberFormatException 60. int len = input
38、.length(); 61. char c, tempChar; 62. Stack<Character> s1 = new Stack<Character>();
39、0;63. Stack<Double> s2 = new Stack<Double>(); 64. Stack<Object> expression = new Stack&
40、lt;Object>(); 65. double number; 66. int lastIndex = -1; 67.
41、60; for (int i=len-1; i>=0; -i) 68. c = input.charAt(i); 69.
42、; if (Character.isDigit(c) 70. lastIndex = readDoubleRevers
43、e(input, i); 71. number = Double.parseDouble(input.substring(lastIndex, i+1); 72.
44、160; s2.push(number); 73. i =
45、0;lastIndex; 74. if (int) number = number) 75. &
46、#160; expression.push(int) number); 76.
47、; else 77. expression.push(number); 78.
48、; else if (isOperator(c) 79. while (!s1.isEmpty() 80.
49、 && s1.peek() != ')' 81.
50、 && priorityCompare(c, s1.peek() < 0) 82. &
51、#160; expression.push(s1.peek(); 83. &
52、#160; s2.push(calc(s2.pop(), s2.pop(), s1.pop(); 84.
53、; 85. s1.push(c); 86.
54、0;else if (c = ')') 87. s1.push(c); 88.
55、 else if (c = '(') 89. while (tempChar=s1.pop()
56、!= ')') 90. expression.push(tempChar); 91.
57、 s2.push(calc(s2.pop(), s2.pop(), tempChar); 92.
58、60; if (s1.isEmpty() 93.
59、160; throw new IllegalArgumentException( 94. &
60、#160; "bracket dosen't match, missing right bracket ')'."); 95.
61、 96. 97.
62、0; else if (c = ' ') 98. / ignore 99.
63、 else 100. throw new
64、 IllegalArgumentException( 101. "wrong character '
65、;" + c + "'"); 102. 103. 104.
66、0; while (!s1.isEmpty() 105. tempChar = s1.pop(); 106.
67、; expression.push(tempChar); 107. s2.push(calc(s2.pop(), s2.pop(), tempChar); 108.
68、 109. while (!expression.isEmpty() 110.
69、; System.out.print(expression.pop() + " "); 111. 112. double result = s2.pop();
70、60; 113. if (!s2.isEmpty() 114. throw new IllegalArgumentException("input is
71、60;a wrong expression."); 115. System.out.println(); 116. if (int) result = result) 117.
72、 System.out.println("the result is " + (int) result); 118. else
73、 119. System.out.println("the result is " + result); 120. 121.
74、 /* 122. * parse the expression, and calculate it. 123. * param input 124. * throws IllegalArgumentExcep
75、tion 125. * throws NumberFormatException 126. */ 127. private static void toReversePolishNotation(String input) 128. &
76、#160; throws IllegalArgumentException, NumberFormatException 129. int len = input.len
77、gth(); 130. char c, tempChar; 131. Stack<Character> s1 = new Stack<Character>();
78、132. Stack<Double> s2 = new Stack<Double>(); 133. double number; 134.
79、60; int lastIndex = -1; 135. for (int i=0; i<len; +i) 136.
80、160; c = input.charAt(i); 137. if (Character.isDigit(c) | c = '.') 138.
81、160; lastIndex = readDouble(input, i); 139.
82、60; number = Double.parseDouble(input.substring(i, lastIndex); 140. s2.push(number);
83、; 141. i = lastIndex - 1; 142.
84、; if (int) number = number) 143. Sys
85、tem.out.print(int) number + " "); 144. else 145. &
86、#160; System.out.print(number + " "); 146.
87、 else if (isOperator(c) 147. while (!s1.isEmpty() 148.
88、; && s1.peek() != '(' 149.
89、0; && priorityCompare(c, s1.peek() <= 0) 150.
90、60; System.out.print(s1.peek() + " "); 151.
91、; double num1 = s2.pop(); 152.
92、0; double num2 = s2.pop(); 153. s2.push(calc(num2, num1, s1.pop(); &
93、#160;154. 155.
94、60; s1.push(c); 156. else if (c = '(') 157.
95、60; s1.push(c); 158. else if (c = ')') 159.
96、60; while (tempChar=s1.pop() != '(') 160.
97、60; System.out.print(tempChar + " "); 161.
98、 double num1 = s2.pop(); 162. double num2 =
99、s2.pop(); 163. s2.push(calc(num2, num1, tempChar); 164.
100、160; if (s1.isEmpty() 165.
101、 throw new IllegalArgumentException( 166.
102、0; "bracket dosen't match, missing left bracket '('."); 167.
103、60; 168. 169.
104、 else if (c = ' ') 170.
105、0; / ignore 171. else 172. &
106、#160; throw new IllegalArgumentException( 173.
107、; "wrong character '" + c + "'"); 174. 175.
108、160; 176. while (!s1.isEmpty() 177. tempChar = s1.pop
109、(); 178. System.out.print(tempChar + " "); 179. &
110、#160; double num1 = s2.pop(); 180. double num2 = s2.pop(); 181.
111、; s2.push(calc(num2, num1, tempChar); 182. 183. double result = s2.pop();
112、 184. if (!s2.isEmpty() 185. throw new IllegalArgumentException("input is
113、 a wrong expression."); 186. System.out.println(); 187. if (int) result = result) 1
114、88. System.out.println("the result is " + (int) result); 189. else
115、60; 190. System.out.println("the result is " + result); 191. 192.
116、60; /* 193. * calculate the two number with the operation. 194. * param num1 195. * param num2
117、;196. * param op 197. * return 198. * throws IllegalArgumentException 199. */ 200
118、. private static double calc(double num1, double num2, char op) 201. throws IllegalArgumentException
119、 202. switch (op) 203. case '+': 204. &
120、#160; return num1 + num2; 205. case '-': 206. &
121、#160; return num1 - num2; 207. case '*': 208. return&
122、#160;num1 * num2; 209. case '/': 210. if (num2 = 0) thr
123、ow new IllegalArgumentException("divisor can't be 0."); 211. return num1 / num2; 212.
124、 default: 213. return 0; / will never catch up here 214. &
125、#160; 215. 216. /* 217. * compare the two operations' priority. 218. &
126、#160; * param c 219. * param peek 220. * return 221. */ 222. private st
127、atic int priorityCompare(char op1, char op2) 223. switch (op1) 224. case '+':
128、160;case '-': 225. return (op2 = '*' | op2 = '/' ? -1 : 0); 226.
129、60; case '*': case '/': 227. return (op2 = '+' | op2 = '
130、-' ? 1 : 0); 228. 229. return 1; 230. 231.
131、160; /* 232. * read the next number (reverse) 233. * param input 234. * param start
132、160;235. * return 236. * throws IllegalArgumentException 237. */ 238. private static int
133、0;readDoubleReverse(String input, int start) 239. throws IllegalArgumentException 240.
134、60; int dotIndex = -1; 241. char c; 242. for (int i=start; i>=0; -i)
135、 243. c = input.charAt(i); 244. if (c =
136、9;.') 245. if (dotIndex != -1) 246. &
137、#160; throw new IllegalArgumentException( 247.
138、; "there have more than 1 dots in the number."); 248.
139、 else 249. dotIndex = i; 250.
140、; else if (!Character.isDigit(c) 251.
141、160;return i + 1; 252. else if (i = 0) 253. &
142、#160; return 0; 254. 255. &
143、#160;256. throw new IllegalArgumentException("not a number."); 257. 258. 259. &
144、#160; /* 260. * read the next number 261. * param input 262. * param start 263.
145、; * return 264. * throws IllegalArgumentException 265. */ 266. private static int readDouble(String i
146、nput, int start) 267. throws IllegalArgumentException 268. int len = input.length(); 269.
147、60; int dotIndex = -1; 270. char c; 271. for (int i=start; i<
148、len; +i) 272. c = input.charAt(i); 273. i
149、f (c = '.') 274. if (dotIndex != -1) 275.
150、 throw new IllegalArgumentException( 276.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論