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

一、表达式定义
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+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值