1. 程式人生 > >Java解析字串表示式--逆波蘭表示式的生成

Java解析字串表示式--逆波蘭表示式的生成

上回講了如何計算字尾表示式,其實真正的難點在於如何將一個正常的字串表示式(中綴表示式)變成一個字尾表示式。如將6 * ( 5 + ( 2 + 3) * 8 + 3)變為6 5 2 3 + 8 * + 3 + *

逆波蘭表示式,它的語法規定,表示式必須以逆波蘭表示式的方式給出。逆波蘭表示式又叫做字尾表示式。這個知識點在資料結構和編譯原理這兩門課程中都有介紹,下面是一些例子:

正常的中綴表示逆波蘭表示式
a+ba,b,+
a+(b-c)a,b,c,-,+
a+(b-c)*da,b,c,-,d,*,+
a+d*(b-c)a,d,b,c,-,*,+

首先約定表示式中運算子的優先順序,從大到小依次為:()、* 和 /、+ 和 -。暫時只考慮四則運算。

順序讀取字串表示式,規則:

  1. 讀到的是運算元,直接輸出;
  2. 讀到的是操作符(+-*/)(記為read),將其與棧頂的操作符(記為top)進行優先順序比較:read>top,read入棧,繼續讀下一個;read≤top,top出棧,並輸出到list中,read繼續和新的top比較;top為空,read直接入棧;若top是“(”,read直接入棧,因為“(”優先順序最高;
  3. 括號的處理:讀到左括號“(”,直接將其壓入棧中,並且除非遇到右括號“)”,“(”是不會彈出的;讀到右括號“)”,將“(”之上的元素全部依次輸出,並彈出“(”但不輸出;

準備:一個棧stack暫存運算子,一個list存放輸出,仍以6 * ( 5 + ( 2 + 3) * 8 + 3)為例。

  1. 讀到“6”,直接輸出【list:6;stack:】
  2. 讀到“*”,與棧頂top比較,top為空,“*”入棧【list:6;stack:*】
  3. 讀到“(”,直接入棧【list:6;stack:*,(】
  4. 讀到“5”,直接輸出【list:6,5;stack:*,(】
  5. 讀到“+”,與棧頂top比較,“+”<“(”,入棧【list:6,5;stack:*,(,+】
  6. 讀到“(”,直接入棧【list:6,5;stack:*,(,+,(】
  7. 讀到“2”,直接輸出【list:6,5,2,;stack:*,(,+,(】
  8. 讀到“+”,與棧頂“(”比較,“+”<“(”,入棧【list:6,5,2,;stack:*,(,+,(,+】
  9. 讀到“3”,直接輸出【list:6,5,2,3,;stack:*,(,+,(,+】
  10. 讀到“)”,輸出“(”之上的元素【list:6,5,2,3,+;stack:*,(,+,】
  11. 讀到“*”,與棧頂的“+”比較, “*”>“+”,“*”入棧【list:6,5,2,3,+;stack:*,(,+,*,】
  12. 讀到“8”,直接輸出【list:6,5,2,3,+,8,;stack:*,(,+,*,】
  13. 讀到“+”,與棧頂的“*”比較,“+”<“*”,“*”出棧並輸出【list:6,5,2,3,+,8,*;stack:*,(,+,】;
  14. “+”,與棧頂的“+”比較,“+”=“+”,“+”出棧並輸出【list:6,5,2,3,+,8,*,+;stack:*,(,】;
  15. “+”,與棧頂的“(”比較,“+”<“(”,“+”入棧【list:6,5,2,3,+,8,*,+;stack:*,(,+】;
  16. 讀到“3”,直接輸出,【list:6,5,2,3,+,8,*,+,3;stack:*,(,+】
  17. 讀到“)”,輸出“(”之上的元素,【list:6,5,2,3,+,8,*,+,3,+;stack:*,】
  18. 輸出棧中所有剩下的,【list:6,5,2,3,+,8,*,+,3,+,*;stack:,】
  19. 最終的字尾表示式就是:6 5 2 3 + 8 * + 3 + *

image

至此,中綴表示式到字尾表示式的任務已經全部完成!

但是需要注意的是,本文中只是做了當運算資料為個位數的處理,當為多位數時該怎麼做呢?

另外當遇到“/”處時,要對被除數進行非0判斷

另外還可以考慮含有負數的運算,含有小數的以及冪運算

那都是資料如何處理的問題了,整體思路應該都差不多!

您的關注是我堅持寫作的動力,如果覺得有用,歡迎關注我的微信,海量學習資源免費送!

你的關注是對我最大的鼓勵!