一、表达式定义
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)
计算中缀表达式或前缀表达式需要定义运算符的优先级
二、算法实现
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 具体执行过程如下