1. 规则
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:
1)首先入栈一个字符‘#’,在中缀表达式的末尾也添加一个字符‘#’。当两个‘#’相遇时运算完成。
2)如果遇到操作数,我们就直接将其输出。
3)如果表达式中的运算符 > 栈中的运算符,则将操作符入栈。(运算符的优先级如表 1-1)
4)如果表达式中的运算符 < 栈中的运算符,弹出栈中的运算符。执行3
5)如果表达式中的运算符 = 栈中的运算符:若是左括号和右括号相遇,括号里的表达式已运算完成弹出左括号,丢弃右括号。若是两“ # ”相遇,表达式转换完成,退出循环。
2. 实例
1)首先读到a,直接输出。
2)读到“+”,将其放入到栈中。
3)读到b,直接输出。
此时栈和输出的情况如下:
4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。
5)读到c,直接输出。
此时栈和输出情况如下:
6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级大于读到的操作符" + ",所以也要弹出并输出。然后再将读到的" + "压入栈中。
此时栈和输出情况如下:
7)下一个读到的为"(",它优先级最高,所以直接放入到栈中。
8)读到d,将其直接输出。
此时栈和输出情况如下:
9)读到" * ",因为栈中“(”优先级比“*”低,所以直接入栈“*”。
10)读到e,直接输出。
此时栈和输出情况如下:
11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。
12)读到f,直接输出。
此时栈和输出情况:
3.代码
import java.util.Stack;
public class Expression {
//存放中缀表达式
private char[] express;
private int length;
public Expression() {
express = new char[1000];
length = 0;
}
/**
* 去除表达式中的空白字符
* @param str
* @return
*/
private boolean StrTrim(String str) {
//取出表达式首尾空白字符
str = str.trim();
if (str.equals("")) {
return false;
}
char[] tmp = str.toCharArray();
for(int i=0; i<tmp.length; i++) {
//提取表达式中的非空字符
if (tmp[i] != ' ') {
express[length] = tmp[i];
length++;
}
}
express[length] = '#';
length++;
return true;
}
/**
* 判断stack,exp的优先级
* @param stack
* @param exp
* @return 返回<,=,>或非法退出
*/
private char Precede(char stack,char exp) {
char f = 0;
switch (exp) {
case '+':
case '-':
if (stack == '(' || stack == '#')
f = '<'; //stack<exp
else
f = '>'; //stack>exp
break;
case '*':
case '/':
if (stack == '*' || stack == '/' || stack == ')') {
f = '>'; //stack>exp
}else {
f = '<'; //stack<exp
}
break;
case '(':
if (stack == ')') {
System.out.println("括号不匹配");
return 0;
}else {
f = '<';
}
break;
case ')':
switch (stack) {
case '(':
f = '=';//左右括号相遇(去括号)
break;
case '#':
System.out.println("缺乏右括号1");
return 0;
default:
f = '>';
break;
}
break;
case '#':
switch (stack) {
case '#':
f = '=';
break;
case '(':
System.out.println("缺乏右括号2");
return 0;
default:
f = '>';
break;
}
}
return f;
}
/**
* 判断c是否为7种运算符之一
* @param c
* @return
*/
private boolean IsExp(char c) {
switch (c) {
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '#':return true;
default:return false;
}
}
/**
* 将中缀表达式转换成后缀表达式
* @param mid
* @return
*/
public char[] Mid2Back(String mid) {
StrTrim(mid);
StringBuffer back = new StringBuffer();
Stack<Character> stack = new Stack<Character>();
stack.push('#');
int i = 0;
char c,s;
c = express[i++];//将表达式的第一个字符赋给c
s = stack.peek();
while (c != '#' || s != '#') {
if (IsExp(c)) {//c是7种运算符之一
switch (Precede(s, c)) {
case '<':
stack.push(c);//栈中元素的优先权低,入栈c
if (i < length) {
c = express[i++];
}
break;
case '=':
s = stack.pop();
if (i < length) {
c = express[i++];
}
break;
case '>':
back.append(stack.pop());//栈顶的元素优先权高,输出
break;
default:
return null;
}
} else {//c不是运算符
back.append(c);
if (i < length) {
c = express[i++];
}
}
s = stack.peek();
}//while 结束
return back.toString().toCharArray();
}
}
public static void main(String[] args) {
Expression expression = new Expression();
String str = "a + (d * e + f) * g";
char[] back = expression.Mid2Back(str);
System.out.println(back);
}