生活随笔
收集整理的這篇文章主要介紹了
前缀、中缀、后缀表达式(转载)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
關鍵字: 概念, 前綴表達式, 前綴記法, 中綴表達式, 中綴記法, 波蘭式, 后綴表達式, 后綴記法, 逆波蘭式
它們都是對表達式的記法,因此也被稱為前綴記法、中綴記法和后綴記法。它們之間的區別在于運算符相對與操作數的位置不同:前綴表達式的運算符位于與其相關的操作數之前;中綴和后綴同理。 舉例: (3 + 4) × 5 - 6 就是中綴表達式 - × + 3 4 5 6?前綴表達式 3 4 + 5 × 6 -?后綴表達式中綴表達式(中綴記法) 中綴表達式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處于操作數的中間。中綴表達式是人們常用的算術表示方法。 雖然人的大腦很容易理解與分析中綴表達式,但對計算機來說中綴表達式卻是很復雜的,因此計算表達式的值時,通常需要先將中綴表達式轉換為前綴或后綴表達式,然后再進行求值。對計算機來說,計算前綴或后綴表達式的值非常簡單。前綴表達式(前綴記法、波蘭式) 前綴表達式的運算符位于操作數之前。前綴表達式的計算機求值: 從右至左掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(棧頂元素 op 次頂元素),并將結果入棧;重復上述過程直到表達式最左端,最后運算得出的值即為表達式的結果。 例如前綴表達式“- × + 3 4 5 6”: (1) 從右至左掃描,將6、5、4、3壓入堆棧; (2) 遇到+運算符,因此彈出3和4(3為棧頂元素,4為次頂元素,注意與后綴表達式做比較),計算出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) 否則,若優先級比棧頂運算符的較高或相等,也將運算符壓入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(棧底->棧頂) S1 (棧底->棧頂) 說明 5 5 空 數字,直接入棧 - 5 - S1為空,運算符直接入棧 ) 5 - ) 右括號直接入棧 4 5 4 - ) 數字直接入棧 × 5 4 - ) × S1棧頂是右括號,直接入棧 ) 5 4 - ) × ) 右括號直接入棧 3 5 4 3 - ) × ) 數字 + 5 4 3 - ) × ) + S1棧頂是右括號,直接入棧 2 5 4 3 2 - ) × ) + 數字 ( 5 4 3 2 + - ) × 左括號,彈出運算符直至遇到右括號 ( 5 4 3 2 + × - 同上 + 5 4 3 2 + × - + 優先級與-相同,入棧 1 5 4 3 2 + × 1 - + 數字 到達最左端 5 4 3 2 + × 1 + - 空 S1中剩余的運算符
因此結果為“- + 1 × + 2 3 4 5”。后綴表達式(后綴記法、逆波蘭式) 后綴表達式與前綴表達式類似,只是運算符位于操作數之后。后綴表達式的計算機求值: 與前綴表達式類似,只是順序是從左至右: 從左至右掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(次頂元素 op?棧頂元素),并將結果入棧;重復上述過程直到表達式最右端,最后運算得出的值即為表達式的結果。 例如后綴表達式“3 4 + 5 × 6 -”: (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) 遇到運算符時,比較其與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中剩余的運算符依次彈出并壓入S2; (8) 依次彈出S2中的元素并輸出,結果的逆序即為中綴表達式對應的后綴表達式(轉換為前綴表達式時不用逆序)。 例如,將中綴表達式“1+((2+3)×4)-5”轉換為后綴表達式的過程如下:
掃描到的元素 S2(棧底->棧頂) S1 (棧底->棧頂) 說明 1 1 空 數字,直接入棧 + 1 + S1為空,運算符直接入棧 ( 1 + ( 左括號,直接入棧 ( 1 + ( ( 同上 2 1 2 + ( ( 數字 + 1 2 + ( ( + S1棧頂為左括號,運算符直接入棧 3 1 2 3 + ( ( + 數字 ) 1 2 3 + + ( 右括號,彈出運算符直至遇到左括號 × 1 2 3 + + ( × S1棧頂為左括號,運算符直接入棧 4 1 2 3 + 4 + ( × 數字 ) 1 2 3 + 4 × + 右括號,彈出運算符直至遇到左括號 - 1 2 3 + 4 × + - -與+優先級相同,因此彈出+,再壓入- 5 1 2 3 + 4 × + 5 - 數字 到達最右端 1 2 3 + 4 × + 5 - 空 S1中剩余的運算符
因此結果為“1 2 3 + 4 × + 5 -”(注意需要逆序輸出)。
編寫Java程序將一個中綴表達式轉換為前綴表達式和后綴表達式,并計算表達式的值。其中的toPolishNotation()方法將中綴表達式轉換為前綴表達式(波蘭式)、toReversePolishNotation()方法則用于將中綴表達式轉換為后綴表達式(逆波蘭式):
注: (1) 程序很長且注釋比較少,但如果將上面的理論內容弄懂之后再將程序編譯并運行起來,還是比較容易理解的。有耐心的話可以研究一下。(2) 此程序是筆者為了說明上述概念而編寫,僅做了簡單的測試,不保證其中沒有Bug,因此不要將其用于除研究之外的其他場合。
[java] ?view plaincopy
package?qmk.simple_test;?? import?java.util.Scanner;?? import?java.util.Stack;?? public?class?Calculator?{?? ??????public?static?final?String?USAGE?=?"==?usage?==\n"?? ????????????+?"input?the?expressions,?and?then?the?program?"?? ????????????+?"will?calculate?them?and?show?the?result.\n"?? ????????????+?"input?'bye'?to?exit.\n";?? ?????? ??????public?static?void?main(String[]?args)?{?? ????????????System.out.println(USAGE);?? ????????????Scanner?scanner?=?new?Scanner(System.in);?? ????????????String?input?=?"";?? ????????????final?String?CLOSE_MARK?=?"bye";?? ????????????System.out.println("input?an?expression:");?? ????????????input?=?scanner.nextLine();?? ????????????while?(input.length()?!=?0?? ??????????????????&&?!CLOSE_MARK.equals((input)))?{?? ??????????????????System.out.print("Polish?Notation?(PN):");?? ??????????????????try?{?? ????????????????????????toPolishNotation(input);?? ??????????????????}?catch?(NumberFormatException?e)?{?? ????????????????????????System.out.println("\ninput?error,?not?a?number.");?? ??????????????????}?catch?(IllegalArgumentException?e)?{?? ????????????????????????System.out.println("\ninput?error:"?+?e.getMessage());?? ??????????????????}?catch?(Exception?e)?{?? ????????????????????????System.out.println("\ninput?error,?invalid?expression.");?? ??????????????????}?? ??????????????????System.out.print("Reverse?Polish?Notation?(RPN):");?? ??????????????????try?{?? ????????????????????????toReversePolishNotation(input);?? ??????????????????}?catch?(NumberFormatException?e)?{?? ????????????????????????System.out.println("\ninput?error,?not?a?number.");?? ??????????????????}?catch?(IllegalArgumentException?e)?{?? ????????????????????????System.out.println("\ninput?error:"?+?e.getMessage());?? ??????????????????}?catch?(Exception?e)?{?? ????????????????????????System.out.println("\ninput?error,?invalid?expression.");?? ??????????????????}?? ??????????????????System.out.println("input?a?new?expression:");?? ??????????????????input?=?scanner.nextLine();?? ????????????}?? ????????????System.out.println("program?exits");?? ??????}?? ?????? ??????private?static?void?toPolishNotation(String?input)?? ??????????????????throws?IllegalArgumentException,?NumberFormatException?{?? ????????????int?len?=?input.length();?? ????????????char?c,?tempChar;?? ????????????Stack<Character>?s1?=?new?Stack<Character>();?? ????????????Stack<Double>?s2?=?new?Stack<Double>();?? ????????????Stack<Object>?expression?=?new?Stack<Object>();?? ????????????double?number;?? ????????????int?lastIndex?=?-1;?? ????????????for?(int?i=len-1;?i>=0;?--i)?{?? ??????????????????c?=?input.charAt(i);?? ??????????????????if?(Character.isDigit(c))?{?? ????????????????????????lastIndex?=?readDoubleReverse(input,?i);?? ????????????????????????number?=?Double.parseDouble(input.substring(lastIndex,?i+1));?? ????????????????????????s2.push(number);?? ????????????????????????i?=?lastIndex;?? ????????????????????????if?((int)?number?==?number)?? ??????????????????????????????expression.push((int)?number);?? ????????????????????????else?? ??????????????????????????????expression.push(number);?? ??????????????????}?else?if?(isOperator(c))?{?? ????????????????????????while?(!s1.isEmpty()?? ????????????????????????????????????&&?s1.peek()?!=?')'?? ????????????????????????????????????&&?priorityCompare(c,?s1.peek())?<?0)?{?? ??????????????????????????????expression.push(s1.peek());?? ??????????????????????????????s2.push(calc(s2.pop(),?s2.pop(),?s1.pop()));?? ????????????????????????}?? ????????????????????????s1.push(c);?? ??????????????????}?else?if?(c?==?')')?{?? ????????????????????????s1.push(c);?? ??????????????????}?else?if?(c?==?'(')?{?? ????????????????????????while?((tempChar=s1.pop())?!=?')')?{?? ??????????????????????????????expression.push(tempChar);?? ??????????????????????????????s2.push(calc(s2.pop(),?s2.pop(),?tempChar));?? ??????????????????????????????if?(s1.isEmpty())?{?? ????????????????????????????????????throw?new?IllegalArgumentException(?? ??????????????????????????????????????????"bracket?dosen't?match,?missing?right?bracket?')'.");?? ??????????????????????????????}?? ????????????????????????}?? ??????????????????}?else?if?(c?==?'?')?{?? ???????????????????????? ??????????????????}?else?{?? ????????????????????????throw?new?IllegalArgumentException(?? ????????????????????????????????????"wrong?character?'"?+?c?+?"'");?? ??????????????????}?? ????????????}?? ????????????while?(!s1.isEmpty())?{?? ??????????????????tempChar?=?s1.pop();?? ??????????????????expression.push(tempChar);?? ??????????????????s2.push(calc(s2.pop(),?s2.pop(),?tempChar));?? ????????????}?? ????????????while?(!expression.isEmpty())?{?? ??????????????????System.out.print(expression.pop()?+?"?");?? ????????????}?? ????????????double?result?=?s2.pop();?? ????????????if?(!s2.isEmpty())?? ??????????????????throw?new?IllegalArgumentException("input?is?a?wrong?expression.");?? ????????????System.out.println();?? ????????????if?((int)?result?==?result)?? ??????????????????System.out.println("the?result?is?"?+?(int)?result);?? ????????????else?? ??????????????????System.out.println("the?result?is?"?+?result);?? ??????}?? ?????? ??????private?static?void?toReversePolishNotation(String?input)?? ??????????????????throws?IllegalArgumentException,?NumberFormatException?{?? ????????????int?len?=?input.length();?? ????????????char?c,?tempChar;?? ????????????Stack<Character>?s1?=?new?Stack<Character>();?? ????????????Stack<Double>?s2?=?new?Stack<Double>();?? ????????????double?number;?? ????????????int?lastIndex?=?-1;?? ????????????for?(int?i=0;?i<len;?++i)?{?? ??????????????????c?=?input.charAt(i);?? ??????????????????if?(Character.isDigit(c)?||?c?==?'.')?{?? ????????????????????????lastIndex?=?readDouble(input,?i);?? ????????????????????????number?=?Double.parseDouble(input.substring(i,?lastIndex));?? ????????????????????????s2.push(number);?? ????????????????????????i?=?lastIndex?-?1;?? ????????????????????????if?((int)?number?==?number)?? ??????????????????????????????System.out.print((int)?number?+?"?");?? ????????????????????????else?? ??????????????????????????????System.out.print(number?+?"?");?? ??????????????????}?else?if?(isOperator(c))?{?? ????????????????????????while?(!s1.isEmpty()?? ????????????????????????????????????&&?s1.peek()?!=?'('?? ????????????????????????????????????&&?priorityCompare(c,?s1.peek())?<=?0)?{?? ??????????????????????????????System.out.print(s1.peek()?+?"?");?? ??????????????????????????????double?num1?=?s2.pop();?? ??????????????????????????????double?num2?=?s2.pop();?? ??????????????????????????????s2.push(calc(num2,?num1,?s1.pop()));?? ????????????????????????}?? ????????????????????????s1.push(c);?? ??????????????????}?else?if?(c?==?'(')?{?? ????????????????????????s1.push(c);?? ??????????????????}?else?if?(c?==?')')?{?? ????????????????????????while?((tempChar=s1.pop())?!=?'(')?{?? ??????????????????????????????System.out.print(tempChar?+?"?");?? ??????????????????????????????double?num1?=?s2.pop();?? ??????????????????????????????double?num2?=?s2.pop();?? ??????????????????????????????s2.push(calc(num2,?num1,?tempChar));?? ??????????????????????????????if?(s1.isEmpty())?{?? ????????????????????????????????????throw?new?IllegalArgumentException(?? ??????????????????????????????????????????"bracket?dosen't?match,?missing?left?bracket?'('.");?? ??????????????????????????????}?? ????????????????????????}?? ??????????????????}?else?if?(c?==?'?')?{?? ???????????????????????? ??????????????????}?else?{?? ????????????????????????throw?new?IllegalArgumentException(?? ????????????????????????????????????"wrong?character?'"?+?c?+?"'");?? ??????????????????}?? ????????????}?? ????????????while?(!s1.isEmpty())?{?? ??????????????????tempChar?=?s1.pop();?? ??????????????????System.out.print(tempChar?+?"?");?? ??????????????????double?num1?=?s2.pop();?? ??????????????????double?num2?=?s2.pop();?? ??????????????????s2.push(calc(num2,?num1,?tempChar));?? ????????????}?? ????????????double?result?=?s2.pop();?? ????????????if?(!s2.isEmpty())?? ??????????????????throw?new?IllegalArgumentException("input?is?a?wrong?expression.");?? ????????????System.out.println();?? ????????????if?((int)?result?==?result)?? ??????????????????System.out.println("the?result?is?"?+?(int)?result);?? ????????????else?? ??????????????????System.out.println("the?result?is?"?+?result);?? ??????}?? ?????? ??????private?static?double?calc(double?num1,?double?num2,?char?op)?? ??????????????????throws?IllegalArgumentException?{?? ????????????switch?(op)?{?? ????????????case?'+':?? ??????????????????return?num1?+?num2;?? ????????????case?'-':?? ??????????????????return?num1?-?num2;?? ????????????case?'*':?? ??????????????????return?num1?*?num2;?? ????????????case?'/':?? ??????????????????if?(num2?==?0)?throw?new?IllegalArgumentException("divisor?can't?be?0.");?? ??????????????????return?num1?/?num2;?? ????????????default:?? ??????????????????return?0;? ????????????}?? ??????}?? ?????? ??????private?static?int?priorityCompare(char?op1,?char?op2)?{?? ????????????switch?(op1)?{?? ????????????case?'+':?case?'-':?? ??????????????????return?(op2?==?'*'?||?op2?==?'/'???-1?:?0);?? ????????????case?'*':?case?'/':?? ??????????????????return?(op2?==?'+'?||?op2?==?'-'???1?:?0);?? ????????????}?? ????????????return?1;?? ??????}?? ?????? ??????private?static?int?readDoubleReverse(String?input,?int?start)?? ??????????????????throws?IllegalArgumentException?{?? ????????????int?dotIndex?=?-1;?? ????????????char?c;?? ????????????for?(int?i=start;?i>=0;?--i)?{?? ??????????????????c?=?input.charAt(i);?? ??????????????????if?(c?==?'.')?{?? ????????????????????????if?(dotIndex?!=?-1)?? ??????????????????????????????throw?new?IllegalArgumentException(?? ????????????????????????????????????"there?have?more?than?1?dots?in?the?number.");?? ????????????????????????else?? ??????????????????????????????dotIndex?=?i;?? ??????????????????}?else?if?(!Character.isDigit(c))?{?? ????????????????????????return?i?+?1;?? ??????????????????}?else?if?(i?==?0)?{?? ????????????????????????return?0;?? ??????????????????}?? ????????????}?? ????????????throw?new?IllegalArgumentException("not?a?number.");?? ??????}?? ???????? ?????? ??????private?static?int?readDouble(String?input,?int?start)?? ??????throws?IllegalArgumentException?{?? ????????????int?len?=?input.length();?? ????????????int?dotIndex?=?-1;?? ????????????char?c;?? ????????????for?(int?i=start;?i<len;?++i)?{?? ??????????????????c?=?input.charAt(i);?? ??????????????????if?(c?==?'.')?{?? ????????????????????????if?(dotIndex?!=?-1)?? ??????????????????????????????throw?new?IllegalArgumentException(?? ??????????????????????????????"there?have?more?than?1?dots?in?the?number.");?? ????????????????????????else?if?(i?==?len?-?1)?? ??????????????????????????????throw?new?IllegalArgumentException(?? ??????????????????????????????"not?a?number,?dot?can't?be?the?last?part?of?a?number.");?? ????????????????????????else?? ??????????????????????????????dotIndex?=?i;?? ??????????????????}?else?if?(!Character.isDigit(c))?{?? ????????????????????????if?(dotIndex?==?-1?||?i?-?dotIndex?>?1)?? ??????????????????????????????return?i;?? ????????????????????????else?? ??????????????????????????????throw?new?IllegalArgumentException(?? ??????????????????????????????"not?a?number,?dot?can't?be?the?last?part?of?a?number.");?? ??????????????????}?else?if?(i?==?len?-?1)?{?? ????????????????????????return?len;?? ??????????????????}?? ????????????}?? ?????????????? ????????????throw?new?IllegalArgumentException("not?a?number.");?? ??????}?? ?????? ??????private?static?boolean?isOperator(char?c)?{?? ????????????return?(c=='+'?||?c=='-'?||?c=='*'?||?c=='/');?? ??????}?? }?? ?
下面是程序運行結果(綠色為用戶輸入):
== usage == input the expressions, and then the program will calculate them and show the result. input 'bye' to exit.
?
input an expression: 3.8+5.3 Polish Notation (PN):+ 3.8 5.3 the result is 9.1 Reverse Polish Notation (RPN):3.8 5.3 + the result is 9.1 input a new expression: 5*(9.1+3.2)/(1-5+4.88) Polish Notation (PN):/ * 5 + 9.1 3.2 + - 1 5 4.88 the result is 69.88636363636364 Reverse Polish Notation (RPN):5 9.1 3.2 + * 1 5 - 4.88 + / the result is 69.88636363636364 input a new expression: 1+((2+3)*4)-5 Polish Notation (PN):- + 1 * + 2 3 4 5 the result is 16 Reverse Polish Notation (RPN):1 2 3 + 4 * + 5 - the result is 16 input a new expression: bye program exits
總結
以上是生活随笔 為你收集整理的前缀、中缀、后缀表达式(转载) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。