中缀表达式转后缀表达式

思路分析:

1) 初始化两个栈:运算符栈s1和储存中间结果的栈s2(s2实际可用ArrayList);
2) 从左至右扫描中缀表达式;
3) 遇到操作数时,将其压s2;
4) 遇到运算符时,比较其与s1栈顶运算符的优先级:

(1)如果 s1 为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(2)否则,若优先级比栈顶运算符的高,也将运算符压入 s1;
(3)否则,将 s1 栈顶的运算符弹出并压入到 s2 中,再次转到 4) - (1) 与 s1 中新的栈顶运算符相比较;

5) 遇到括号时:

(1) 如果是左括号“(”,则直接压入s1
(2) 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃

6) 重复步骤2)至5),直到表达式的最右边
7) 将s1中剩余的运算符依次弹出并压入s2
8) 依次弹出s2中的元素并输出,结果的逆序(若s2为ArrayList则直接输出)即为中缀表达式对应的后缀表达式


举例:

将中缀表达式“1+((2+3)×4)-5”转换为后缀表达式的过程如下,结果为 "1 2 3 + 4 × + 5 –"

 

 

代码实现:

1. class infixTosuffix {  
2.   
3.     /** 
4.      * 将Sting数组转为ArrayList 
5.      * @param s 
6.      * @return 
7.      */  
8.     public static List<String> toinfixExpList(String[] s) {  
9.         ArrayList<String> list = new ArrayList<>();  
10.         for (String s1 : s) {  
11.             list.add(s1);  
12.         }  
13.         return list;  
14.     }  
15.   
16.     /** 
17.      * 中缀表达式转为后缀表达式的具体实现 
18.      * @param infixExpList 
19.      * @return 
20.      */  
21.     public static List<String> toSuffixExpr(List<String> infixExpList) {  
22.         Stack<String> s1 = new Stack<>();//符号栈  
23.   
24.         //说明:因为 s2 这个栈,在整个转换过程中,没有 pop 操作,而且后面我们还需要逆序输出  
25.         //因此比较麻烦,这里我们就不用 Stack<String>  直接使用 List<String> s2  
26.         ArrayList<String> s2 = new ArrayList<>();//存储中间结果的ArrayList  
27.   
28.   
29.         for (String s : infixExpList) {  
30.             if (Polandnotation.isNumeric(s)) {//如果是一个数,加入 s2  
31.                 s2.add(s);  
32.             } else if (s1.size() == 0 || s.equals("(")) {  
33.                 s1.push(s);  
34.             } else if (s.equals(")")) {/*如果是右括号“)”,则依次弹出 s1 栈顶的运算符,并压入 s2, 
35.                                          直到遇到左括号则结束,最后将这一对括号丢弃*/  
36.                 while (!s1.peek().equals("(")) {  
37.                     s2.add(s1.pop());  
38.                 }  
39.                 s1.pop();  //还要将 “(” 弹出 s1 栈, 消除一对小括号  
40.             } else {  
41.                 /*当 item 的优先级小于等于 s1 栈顶运算符, 
42.                 将 s1 栈顶的运算符弹出并加入到 s2 中,再次转到(4.1) 与 s1 中新的栈顶运算符相比较*/  
43.   
44. //                bug:这种写法s1.peek()可能为“(”,getPriority会走default  
45. //                while (s1.size() != 0 &&  
46. //                       infixTosuffix.getPriority(s) <= infixTosuffix.getPriority(s1.peek())) {  
47. //                    s2.add(s1.pop());  
48. //                }  
49.                 while (s1.size() != 0) {  
50.                     int sPriority = infixTosuffix.getPriority(s);  
51.                     if (s1.peek().equals("(")) {  
52.                         break;  
53.                     }  
54.                     int topPriority = infixTosuffix.getPriority(s1.peek());  
55.                     if (sPriority <= topPriority) {  
56.                         s2.add(s1.pop());  
57.                     }  
58.                 }  
59.                 s1.push(s);//还需要将 item 压入栈  
60.             }  
61.         }  
62.   
63.         while (s1.size() != 0) {//将 s1 中剩余的运算符依次弹出并加入 s2  
64.             s2.add(s1.pop());  
65.         }  
66.   
67.         return s2; //注意因为是存放到 List, 因此按顺序输出就是对应的后缀表达式对应的 List  
68.     }  
69.   
70.     /** 
71.      * 获取运算符的优先级 
72.      * @param s 
73.      * @return 
74.      */  
75.     public static int getPriority(String s) {  
76.         switch (s) {  
77.             case "+":  
78.                 return 1;  
79.             case "-":  
80.                 return 1;  
81.             case "*":  
82.                 return 2;  
83.             case "/":  
84.                 return 2;  
85.             default:  
86.                 throw new RuntimeException("getPriority(): ERROR!!!!!");  
87.         }  
88.     }  
89. }  

来自 <http://www.planetb.ca/projects/syntaxHighlighter/popup.php> 

 

posted @ 2020-10-16 11:20  白刃天使  阅读(435)  评论(0编辑  收藏  举报