1. 前言
假设我们已经知道中缀表达式和后缀表达式的概念. 我们可以用符号栈来实现中缀表达式向后缀表达式的转变.
2. 符号栈实现中缀表达式转变为后缀表达式
(1). 思路
我们设计了可变字符串与符号栈. 如果传入的字符串的字符是数字字符,则直接将该字符append到stringbuilder中. 如果该字符是符号字符,首先先判断符号栈是否为空,如果为空,则直接将该字符压栈,如果不为空,则需要将该字符与栈顶字符进行优先级比较.如果栈顶元素的优先级>该字符,毫无疑问,直接将栈顶元素弹栈.如果栈顶元素与该元素优先级相等,由于计算的顺序是从左到右,所以仍然需要将栈顶元素弹栈. 弹栈过程结束以后,需要将该字符压栈.
(2). 解
//将中缀表达式转变为后缀表达式
//目前只讨论没有小括号的情况
public class postfixexpr {
public StringBuilder postfix(String s) throws Exception {
//符号栈
Deque<Character> deque = new LinkedList<>();
StringBuilder str = new StringBuilder();
int i = 0;
for (; i < s.length(); i++) {
char c = s.charAt(i);
//如果该字符是数字字符, 那么将该字符加入到可变字符串
if(isNumber(c)) {
str.append(c);
} else {
//如果栈空, 则直接将该符号压栈
//如果不为空, 则将栈顶元素与该字符作比较
//if栈顶元素优先级大于等于该元素, 全部弹栈
if(deque.isEmpty()) {
deque.push(c);
} else {
while(!deque.isEmpty() && priority(deque.peek()) >= priority(c)){
str.append(deque.pop());
}
deque.push(c);
}
}
}
while(!deque.isEmpty()) {
str.append(deque.pop());
}
return str;
}
//设计判断符号优先级的函数
private int priority(char c) throws Exception {
if (c == '+' || c == '-') {
return 1;
} else if (c == '*' || c == '/') {
return 2;
} else {
throw new Exception();
}
}
private boolean isNumber(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/') {
return false;
}
return true;
}
}
(3). 单元测试
public class postfixexprTest {
@Test
public void test() throws Exception {
postfixexpr pf = new postfixexpr();
// System.out.println(pf.postfix("a+b*c"));
//abc*+
System.out.println(pf.postfix("a*b-c/d"));
//ab*cd/-
}
}
3. 带小括号的中缀表达式转变为后缀表达式
(1). 思路
将括号的优先级设置为最低,避免括号提前出栈. 如果是左括号,直接将其入栈,如果遇到右括号,一直出栈,直到遇到左括号,此时再将左括号出栈. 遇到其他符号情况与上同.
(2). 解
public class postfixexpr2 {
public StringBuilder postfix(String s) throws Exception {
//符号栈
Deque<Character> deque = new LinkedList<>();
StringBuilder str = new StringBuilder();
int i = 0;
for (; i < s.length(); i++) {
char c = s.charAt(i);
//如果该字符是数字字符, 那么将该字符加入到可变字符串
if(isNumber(c)) {
str.append(c);
} else {
if(deque.isEmpty()) {
deque.push(c);
} else {
if(c == '(') {
deque.push(c);
}else if(c == ')') {
while(deque.peek() != '(') {
str.append(deque.pop());
}
//将字符'('弹栈
deque.pop();
} else {
while(!deque.isEmpty() && priority(deque.peek()) >= priority(c)){
str.append(deque.pop());
}
deque.push(c);
}
}
}
}
while(!deque.isEmpty()) {
str.append(deque.pop());
}
return str;
}
//设计判断符号优先级的函数
private int priority(char c) throws Exception {
if (c == '+' || c == '-') {
return 1;
} else if (c == '*' || c == '/') {
return 2;
} else if(c == '('){
return 0;
} else {
throw new Exception();
}
}
private boolean isNumber(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {
return false;
}
return true;
}
}
(3). 单元测试
public class postfixexpr2Test {
@Test
public void test() throws Exception {
postfixexpr2 pf = new postfixexpr2();
// System.out.println(pf.postfix("(a+b)*c"));
//ab+c*
System.out.println(pf.postfix("a*(b+c)"));
//abc+*
}
}