您的位置:首页 > 其它

栈应用2 中缀表达式转后缀表达式

2017-06-26 09:20 441 查看
一、表达式定义

1.1 中缀表达式

    中缀表达式由一个单一字符或运算符,连接前后两个中缀字符串共同组成

    A+B

    A

     (A+B)+(C-D)

1.2 前缀表达式

    前缀表达式由一个单一字符或运算符,随后是两个前缀表达式共同组成。每个前缀字符串长度大于1,包含一个运算符、第一个操作数和第二个操作数。

    A    +AB   ++AB-CD

1.3 后缀表达式

    后缀表达式由两个后缀字符串,随后是一个单一字符或运算符共同组成。每个后缀字符串长度大于1,包含第一个操作数和第二个操作数,随后是一个运算符。

    A   AB+    AB+CD-+  

前缀表达式是无需括号描述数学表达式的方法。计算后缀和前缀表达式的时间开销是O(n)

中缀    前缀    后缀
A+B    +AB    AB+
A+B-C    -+ABC    AB+C-
(A+B)*C-D    -*+ABCD    AB+C*D-    
计算中缀表达式或前缀表达式需要定义运算符的优先级

符号    运算符    优先级    相关性
()

[]
小括号

中括号    
17    从左向右


/

 %      
乘号

除号

取余
15    从左向右
+

-    
加号

减号    
12    从左向右
二、算法实现

2.1 算法逻辑

    只需要一个栈就可以将中缀表达式转换为后缀表达式。利用栈把表达式中远算法的次序从中序变后序。栈中仅存储运算符和左括号。由于后缀表达式中不包括括号,所以输出后缀表达式时将不输出括号。

  算法:

    a)创建一个栈

    b)遍历所有字符 t

        c)如果t是一个操作数,输出t

        d)如果t是右括号,出栈并输出该符号,直至一个左括号出栈,但左括号不输出。

        e)如果t是左括号。出栈输出该符号,直至出现一个比t的优先级小的符号,或者出现一个左括号,或者栈空,t入栈

    f)出栈输出该符号直至栈空

2.2 算法代码

    运算符枚举

    

1
2
import java.util.HashMap;
3
import java.util.Map;
4
5
/**
6
* Created by Administrator on 2017/6/24 0024.
7
*/
8
public enum OperatorEnum {
9
   LEFT_PARENTHESIS(17,"(","左括号,从左到右"),
10
   RIGHT_PARENTHESIS(17,")","右括号,从左到右"),
11
   LEFT_BRACKET(17,"[","左中括号,从左到右"),
12
   RIGHT_BRACKET(17,"]","右中括号,从左到右"),
13
   PLUS_SIGN(12,"+","加号,从左向右"),
14
   MINUS(12,"-","减号,从左向右"),
15
   TIMES_SIGN(13,"*","称号"),
16
   DIVISION_SIGN(13,"/","除号");
17
18
   private int level;//优先级
19
   private String msg;//运算描述
20
   private String opertor;//运算符
21
22
23
   public int getLevel() {
24
       return level;
25
   }
26
27
28
   public String getMsg() {
29
       return msg;
30
   }
31
32
   public String getOpertor() {
33
       return opertor;
34
   }
35
36
   /**
37
    * 用于存储运算符和优先级的关系
38
    */
39
   private static Map<String,Integer> map = new HashMap<>();
40
   static  {
41
       OperatorEnum[] values = OperatorEnum.values();
42
       for (OperatorEnum opertorEnum: values) {
43
         map.put(opertorEnum.getOpertor(), opertorEnum.getLevel());
44
       }
45
   }
46
   OperatorEnum(int level, String opertor, String msg) {
47
       this.level = level;
48
       this.msg = msg;
49
       this.opertor = opertor;
50
   }
51
   /**
52
    * 判断符号是否是运算符,不是运算符就默认为操作数
53
    * @param opertor
54
    * @return
55
    */
56
   public static boolean isOperator(String opertor){
57
       return map.get(opertor) != null;
58
   }
59
60
   /**
61
    * 获取运算符的优先级
62
    * @param opertor
63
    * @return
64
    */
65
   public static int getOperatorLevel(String opertor){
66
       if(!isOperator(opertor)){
67
         return 0;
68
       }
69
       return map.get(opertor);
70
   }
71
72
   /**
73
    * 判断是否是右括号
74
    * @param opertor
75
    * @return
76
    */
77
   public static boolean isRightSign(String opertor){
78
       return RIGHT_PARENTHESIS.getOpertor().equals(opertor);
79
   }
80
81
   /**
82
    * 判断是否是左括号
83
    * @param opertor
84
    * @return
85
    */
86
   public static boolean isLeftSign(String opertor){
87
       return LEFT_PARENTHESIS.getOpertor().equals(opertor);
88
   }
89
}
90
    算法实现:
    





 

1

import java.util.Stack;


2



3

/**


4

* Created by Administrator on 2017/6/24 0024.


5

*/


6

public class OperatorStack {


7



8

   public static void main(String[] args) {


9

       String str = "A*B-(C+D)+E";


10

       System.out.println(changeOperator(str));


11

   }


12

   public static String changeOperator(String str){


13

       char[] chars = str.toCharArray();


14



15

       //用于存储运算符


16

       java.util.Stack<String> stack = new Stack<>();


17



18

       //用于存储转换后的结果


19

       StringBuilder stringBuilder = new StringBuilder();


20

       


21

       //遍历所有字符


22

       for(char c : chars){


23

          String s = String.valueOf(c);


24

          


25

          


26

          if(!OperatorEnum.isOperator(s)){


27

              


28

              //如果不是运算符,就是操作数,直接输出


29

              stringBuilder.append(s);


30

          }else if(OperatorEnum.isRightSign(s)){


31

              


32

              //如果是右括号,就出栈输出该符号,直到出现左括号。


33

              while(true){


34

                 String s1 = stack.pop();


35

                 if(OperatorEnum.isLeftSign(s1)){


36

                     break;


37

                 }


38

                 stringBuilder.append(s1);


39

             }


40

          }else if(OperatorEnum.isOperator(s)){


41



42

              


43

              //如果是左括号和运算符


44

              while(!stack.isEmpty()){


45

                 


46

                 //就出栈输出该符号,直到出现  优先级的运算符或者出现左括号,或者栈空


47

                 String s1 = stack.peek();


48

                 if(OperatorEnum.isLeftSign(s1) || OperatorEnum.getOperatorLevel(s1) < OperatorEnum.getOperatorLevel(s)){


49

                     break;


50

                 }


51

                 stack.pop();


52

                 stringBuilder.append(s1);


53

             }


54



55

              stack.push(s);


56

          }


57

       }


58

       


59

       //遍历完字符后,出栈输出符号直至栈空


60

       while(!stack.isEmpty()){


61

          stringBuilder.append(stack.pop());


62

       }


63

       return stringBuilder.toString();


64

   }


65

}


66



2.3 算法追踪

    假设现有表达式为A*B-(C+D)+E 具体执行过程如下

    

输入字符    对栈执行的操作   栈    后缀表达式
A输出     A
*    入栈    *    A
B输出    *    AB
-检查,入栈    -    AB*
(    检查,入栈    -(    AB*
C输出    -(    AB*C
+检查,入栈     -(+    AB*C
D输出    -(+    AB*C
)检查,入栈-    AB*C+
+检查,入栈    +    AB*C+-
E    输出    +    AB*C+-E
输入结束    出栈直至栈空     AB*C+-E+
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐