栈应用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)
计算中缀表达式或前缀表达式需要定义运算符的优先级
二、算法实现
2.1 算法逻辑
只需要一个栈就可以将中缀表达式转换为后缀表达式。利用栈把表达式中远算法的次序从中序变后序。栈中仅存储运算符和左括号。由于后缀表达式中不包括括号,所以输出后缀表达式时将不输出括号。
算法:
a)创建一个栈
b)遍历所有字符 t
c)如果t是一个操作数,输出t
d)如果t是右括号,出栈并输出该符号,直至一个左括号出栈,但左括号不输出。
e)如果t是左括号。出栈输出该符号,直至出现一个比t的优先级小的符号,或者出现一个左括号,或者栈空,t入栈
f)出栈输出该符号直至栈空
2.2 算法代码
运算符枚举
12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2.3 算法追踪
假设现有表达式为A*B-(C+D)+E 具体执行过程如下
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 算法代码
运算符枚举
12
import java.util.HashMap;3
import java.util.Map;45
/**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,"/","除号");1718
private int level;//优先级19
private String msg;//运算描述20
private String opertor;//运算符212223
public int getLevel() {24
return level;25
}262728
public String getMsg() {29
return msg;30
}3132
public String getOpertor() {33
return opertor;34
}3536
/**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 opertor54
* @return55
*/56
public static boolean isOperator(String opertor){57
return map.get(opertor) != null;58
}5960
/**61
* 获取运算符的优先级62
* @param opertor63
* @return64
*/65
public static int getOperatorLevel(String opertor){66
if(!isOperator(opertor)){67
return 0;68
}69
return map.get(opertor);70
}7172
/**73
* 判断是否是右括号74
* @param opertor75
* @return76
*/77
public static boolean isRightSign(String opertor){78
return RIGHT_PARENTHESIS.getOpertor().equals(opertor);79
}8081
/**82
* 判断是否是左括号83
* @param opertor84
* @return85
*/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+ |
相关文章推荐
- C++数据结构与STL--栈的应用--中缀表达式转后缀表达式
- 栈的应用 - 中缀表达式转后缀表达式
- 栈应用2 中缀表达式转后缀表达式
- [置顶] 栈应用:中缀表达式转后缀表达式(运算结果保证正确)
- 栈的应用实例——中缀表达式转换为后缀表达式
- java 栈 Stack类 栈的应用--中缀表达式转后缀表达式并计算
- 栈的应用 后缀表达式求值 后缀表达式与中缀表达式的转换
- 《数据结构实战》中缀表达式转后缀表达式----栈的应用
- Chapter4:栈的应用-将中缀表达式转换为后缀表达式
- 栈的应用案例2:中缀表达式转后缀表达式
- 栈应用(中缀表达式转后缀表达式并计算后缀表达式的值)
- 栈的应用——中缀表达式转后缀表达式,后缀表达式的求值,中缀表达式求值
- 中缀表达式转后缀表达式求值(栈的应用)
- 栈的应用 - 中缀表达式转后缀表达式
- 栈应用:中缀表达式转后缀表达式并以二叉树储存
- 栈的应用(一)——中缀表达式转后缀表达式
- java中的栈Stack的基本使用和应用(二) ——利用栈计算合法的算术表达,中缀表达式转后缀表达式
- C++栈的应用——后缀表达式求值、中缀表达式到后缀表达式的转换
- 【数据结构】栈的应用---四则运算表达式求值(中缀表达式与后缀表达式转换)
- 栈应用(中缀表达式转后缀表达式并计算后缀表达式的值)