棧的應用之中綴運算式轉尾碼運算式

來源:互聯網
上載者:User

標籤:

1,中綴運算式的定義及為什麼要將中綴運算式轉換為尾碼運算式?

中綴運算式(中綴記法)
中綴運算式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處於運算元的中間。中綴運算式是人們常用的算術表示方法。
雖然人的大腦很容易理解與分析中綴運算式,但對電腦來說中綴運算式卻是很複雜的,因此計算運算式的值時,通常需要先將中綴運算式轉換為首碼或尾碼運算式,然後再進行求值。對電腦來說,計算首碼或尾碼運算式的值要比中綴運算式簡單。

比如,電腦計算尾碼運算式的過程如下----尾碼運算式的電腦求值:
從左至右掃描運算式,遇到數字時,將數字壓入堆棧,遇到運算子時,彈出棧頂的兩個數,用運算子對它們做相應的計算(次棧頂元素 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,由此得出最終結果。

 

2,中綴運算式轉換為尾碼運算式演算法:

這裡只用了一個棧來儲存掃描中綴運算式時遇到的運算子。掃描過程中運算的運算元則直接 append 到輸出運算式的末尾

?運算子在何種情況下壓入棧?

若當前掃描的運算子的優先順序大於棧頂運算子的優先順序,則進行入棧。

若當前掃描的運算子的優先順序與棧頂運算子的優先順序相同,則需要判斷當前掃描的運算子運算時的結合方向,若結合方向為從左至右,則不需要入棧;若結合方向為從右至左,則入棧。其中,加、減、乘、除 運算子的結合方向為從左至右,而求冪運算子的結合方向為從右至左。由於求冪運算子的最優級最高且它的結合方向為從右至左,故掃描遇到求冪運算子時直接將其入棧。

?對於中綴運算式中的括弧的處理

左括弧總是被壓入棧。一旦左括弧在棧中,就被當作優先順序最低的運算子來對待,即:任何一個後繼的運算子都將被壓入棧。在遇到一個右括弧時,從棧中彈出運算子並將它們添加到輸出運算式末尾,直至彈出一個左括弧為止(尾碼運算式中沒有括弧,當然括弧也就不需要添加到輸出運算式了)。然後,演算法再繼續....

 

在從左向右處理中綴運算式的過程中,根據遇到的符號,執行下列動作:

①運算元         每個運算元都添加到輸出運算式末尾(輸出運算式就是最終得到的尾碼運算式結果)

②運算子 ^(求冪運算)       ^ 壓入棧(因為在所有的運算子中(加、減、乘、除、求冪)求冪運算的優先順序最高,且求冪運算的結合方式為從右至左)

③運算子 + -  * /     從棧中彈出運算子,並將它們添加到輸出運算式末尾,直至棧空或者棧頂優先順序比新的運算子低,然後再將新的運算子壓入棧

④左括弧 (      壓入棧

⑤右括弧 )     從棧中彈出運算子,將它們添加到輸出運算式末尾,直至彈出一個左括弧,丟棄這兩個括弧

 

3,具體的中綴運算式轉尾碼運算式的JAVA代碼實現

注意:程式中用來存放操作符的棧 不是 JDK 中java.util 包的Stack,而是自己實現的Stack。參考:使用JAVA數組實現順序棧

 1 import list.SequenceStack; 2 import list.Stack; 3  4 public class Postfix { 5     /* 6      * @Task: 將中綴運算式轉換為尾碼運算式 7      * @param: infix 合法的中綴運算式字串 8      * @return: 與infix等價的尾碼運算式字串 9      */10     public static String convert2Postfix(String infix){11         StringBuffer postfix = new StringBuffer();//初始化一個字串緩衝區存放轉換過程中產生的尾碼運算式12         Stack<Character> operatorStack = new SequenceStack<Character>();13         int characterCount = infix.length();14         char topCharactor;15         16         for(int index = 0; index < characterCount; index++){17             boolean done = false;18             char nextCharacter = infix.charAt(index);19             if(isVariable(nextCharacter))20                 postfix = postfix.append(nextCharacter);21             else{22                 switch(nextCharacter)23                 {24                 case ‘^‘:25                     operatorStack.push(nextCharacter);26                     break;27                 case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘:28                     while(!done && !operatorStack.empty()){29                         topCharactor = operatorStack.peek();30                         if(getPrecedence(nextCharacter) <= getPrecedence(topCharactor)){31                             postfix = postfix.append(topCharactor);32                             operatorStack.pop();33                         }34                         else35                             done = true;//當棧頂元素逐漸pop後,nextCharacter的優先順序大於 棧頂的優先順序36                     }//end while37                     operatorStack.push(nextCharacter);//當nextCharacter的優先順序大於 棧頂的優先順序,再把nextCharacter push 入棧38                     break;39                 case ‘(‘:40                     operatorStack.push(nextCharacter);41                     break;42                 case ‘)‘:43                     topCharactor = operatorStack.pop();44                     while(topCharactor != ‘(‘){45                         postfix = postfix.append(topCharactor);46                         topCharactor = operatorStack.pop();47                     }48                     break;49                 default:break;50                 }//end switch51             }52         }//end for53         54         while(!operatorStack.empty()){55             topCharactor = operatorStack.pop();56             postfix = postfix.append(topCharactor);57         }58         return postfix.toString();59     }60     61     private static int getPrecedence(char operator){62         switch(operator)63         {64         case ‘(‘: case ‘)‘: return 0;//實際只有 + - * / 才需要調用該函數比較優先順序65         case ‘+‘: case ‘-‘: return 1;// + - 優先順序為166         case ‘*‘: case ‘/‘: return 2;// * / 優先順序為267         case ‘^‘:             return 3;68         }69         return -1;70     }71     72     //運算元預設用字母來表示73     private static boolean isVariable(char charactor){74         return Character.isLetter(charactor);75     }76     77     //for test purpose78     public static void main(String[] args) {79         String postfix = convert2Postfix("a/b*(c +(d-e))");80         System.out.println(postfix);81     }82 }

 

參考資料:首碼、中綴、尾碼運算式

演算法詳細解釋參考《資料結構與演算法JAVA語言描述第二版》--Frank M.Carrano 著.第21章

棧的應用之中綴運算式轉尾碼運算式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.