日常算数中是将一个操作符放在两个操作数中间的比如:1+2。因为是把操作符写在操作数中间,所以这种表达法被称为中缀表达法。
而后缀表达法,也叫做波兰逆序表达法(Reverse Polish Notation RPN),它是由一位波兰数学家发明的,操作符跟在两个操作数后面,这样A+B 就可以表示为AB+,
A/B 表示为 AB/。
如下所示:
中缀表达式 后缀表达式
A+B-C AB+C-
A*B/C AB*C/
A+B*C ABC*+
A*B+C AB*C+
A*(B+C) ABC+C
A*B+C*D AB*CD*+
(A+B)*(C-D) AB+CD-*
((A+B)*C)-D AB+C*D-
A+B*(C-D/(E+F)) ABCDEF+/-*+
此处仅仅讨论加减乘除和括号这几种操作符,剩余的比如说乘方,根号等暂时不做讨论。
林外除了中缀表达法还有一种前缀表达法,即操作符写在两个操作数前面,这种表达法和后缀表达法类似但是很少使用。一下主要讨论两个问题1、怎样把中缀表达式转换成后缀表达式。2、怎么计算一个后缀表达式的值。
一、如何把一个中缀表达式转换成后缀表达式:
在转换过程中常使用栈这种数据结构,具体的规则如下
从左到右依次从一个中缀式中读取一个字符
1、如果该字符为操作数,则立刻输出;
2、如果该字符为左括号'(' 则立即将其压栈;
3、如果该字符为一个操作符:
3.1、如果栈为空,或者栈顶元素为左括号'(',则立即将该操作符压栈;
3.2、如果栈顶操作符的优先级小于他自己,则立即将该操作符压栈;
3.3、如果栈顶操作符优先级大于等于自己,则先将栈顶元素出栈,保存为临时变量,先将自己压栈,在将临时变量压栈;
4、如果该字符为右括号'(',则依次从栈中弹出元素,直至栈为空或者弹出元素为左括号。
5、如果表达式遍历完毕,则依次出栈,直至栈空
以下为java代码:Infix类接收一个中缀式作为参数,输出一个后缀式,Test类为测试类
import java.util.Stack;
public class Infix {
Stack<Character> stack;
String inputStr;
String outputStr = "";
public Infix(String inputStr) {
super();
this.inputStr = inputStr;
stack = new Stack<Character>();
train();
System.out.println("\n"+outputStr+"\n");
}
// 中缀表达式转换成后缀表达式
private void train() {
for (int i = 0; i < inputStr.length(); i++) {
System.out.print(inputStr.charAt(i));
readin(inputStr.charAt(i));
}
while(!stack.isEmpty()){
outputStr+=stack.pop();
}
}
// 依次从左到右每次读入一个字符
private void readin(char charAt) {
switch (charAt) {
// 加号拥有同样的优先级
case '+':
case '-':
addOption1(charAt);
break;
// 乘号和除号拥有同样的优先级
case '*':
case '/':
addOption2(charAt);
break;
case '(':
addOption3(charAt);
break;
case ')':
addOption4(charAt);
break;
default:
addNum(charAt);
break;
}
}
private void addNum(char charAt) {
outputStr += charAt;
}
private void addOption4(char charAt) {
while (!stack.isEmpty()&&stack.peek()!='(') {
outputStr+=stack.pop();
}
stack.pop();
}
private void addOption3(char charAt) {
stack.push(charAt);
}
private void addOption2(char charAt) {
if(stack.isEmpty()||stack.peek()=='('){
stack.push(charAt);
}else if(stack.peek()=='+'||stack.peek()=='-'){
stack.push(charAt);
}else {
Character temp = stack.pop();
stack.push(charAt);
stack.push(temp);
}
}
private void addOption1(char charAt) {
if(stack.isEmpty()||stack.peek()=='('){
stack.push(charAt);
}else if (stack.peek()=='*'||stack.peek()=='/') {
outputStr+=stack.pop();
stack.push(charAt);
}else {
Character temp = stack.pop();
stack.push(charAt);
stack.push(temp);
}
}
}
public class Test {
public static void main(String[] args) {
Infix infix = new Infix("1+2*(4-3)");
Infix infix2 = new Infix("(1+2)-(2+3)");
Infix infix3 = new Infix("a+b*c");
Infix infix4 = new Infix("a*(b+c)");
Infix infix5 = new Infix("a+b*(c-d)");
Infix infix6 = new Infix("A+B*(C-D/(E+F))");
Infix infix7 = new Infix("((A+B)*C)-D");
Infix infix8 = new Infix("(A+B)*(C-D) ");
}
}
测试结果如下
1+2*(4-3)
1243-*+
(1+2)-(2+3)
12+23+-
a+b*c
abc*+
a*(b+c)
abc+*
a+b*(c-d)
abcd-*+
A+B*(C-D/(E+F))
ABCDEF+/-*+
((A+B)*C)-D
AB+C*D-
(A+B)*(C-D)
AB+CD- *