一、需求分析
1、给定一个中缀表达式"( 3 + 4 ) * 5 + 6";
2、将其转换为后缀表达式,并计算结果。
二、思路分析
1、需要使用两个栈,一个用于存放后缀表达式的中间结果(tempStack)和一个用于存放操作符(operStack);
2、扫描到"(",此时operStack为空,直接入栈
operStack => “(”
3、扫描到"3",数字直接入栈tempStack
tempStack => “3”
operStack => “(”
4、扫描到"+",优先级大于operStack栈顶元素的优先级,直接入栈operStack
tempStack => “3”
operStack => “(”,"+"
5、扫描到"4",数字直接入栈tempStack
tempStack => “3”,“4”
operStack => “(”,"+"
6、扫描到")",优先级最高,将operStack中元素依次弹出并入栈tempStack,遇见"(“停止
tempStack => “3”,“4”,”+"
operStack =>
7、扫描到"*",此时operStack为空,直接入栈
tempStack => “3”,“4”,"+"
operStack => “*”
8、扫描到"5",数字直接入栈tempStack
tempStack => “3”,“4”,"+",“5”
operStack => “*”
9、扫描到"+",其优先级低于operStack栈顶元素"*“的优先级且不是”(",将"*“弹出并压入到tempStack中,然后将”+“入栈operStack
tempStack => “3”,“4”,”+",“5”,"*"
operStack => “+”
10、扫描到"6",数字直接入栈tempStack
tempStack => “3”,“4”,"+",“5”,"*",“6”
operStack => “+”
11、扫描完毕,依次将operStack中元素弹出并入栈tempStack
tempStack => “3”,“4”,"+",“5”,"*",“6”,"+"
operStack =>
12、转换结束,此时将tempStack中元素依次弹出,其逆序就是后缀表达式
三、代码
package com.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 例如:(3+5)\*5-6对应的后缀表达式为3 5 + 5 \* 6 -,其求值步骤如下: 1.从左到右扫描,遇见数字直接入栈,3和5入栈;
* 2.遇见操作符+,从栈中弹出两个数3和5,根据操作符计算结果为8,并将结果8入栈; 3.将5入栈;
* 4.遇见操作符*,弹出两个操作符5和8,计算结果为5*8=40,将40入栈; 5.将6入栈;
* 6.遇见操作符-,弹出两个数字6和40,计算结果为40-6=34,将34入栈; 7.字符串扫描完毕,栈中剩余数字34就是最终答案。
*
* @author chaixf
*
*/
public class PolandNotation {
public static void main(String[] args) {
// 中缀表达式(3+4)*5+6
String midExpression = "3 + ( 3 + 4 ) * 6 / 3";
String ress = midToSuffix(midExpression);
System.out.println(midExpression + "的后缀表达式为:" + ress);
System.out.println("后缀表达式的计算结果为:" + calculate(getListString(ress)));
}
/**
* 将字符串分割
*
* @param suffixExpression
* @return 一个list
*/
public static List<String> getListString(String suffixExpression) {
// 将suffixExpression进行分割
String[] split = suffixExpression.split(" ");
// 将split放进ArrayList中
ArrayList<String> arrayList = new ArrayList<String>();
for (String item : split) {
arrayList.add(item);
}
return arrayList;
}
/**
* 计算后缀表达式的结果
*
* @param list
* @return 一个整数结果
*/
public static int calculate(List<String> list) {
// 创建一个栈
Stack<Integer> stack = new Stack<Integer>();
for (String item : list) {
if (item.matches("\\d+")) {// 匹配到的是数字
stack.push(Integer.parseInt(item));
} else {// 匹配到的是操作符
// 弹出两个数并计算结果
int num2 = stack.pop();
int num1 = stack.pop();
int result = 0;
switch (item) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
result = num1 / num2;
break;
default:
throw new RuntimeException("操作符错误!");
}
// 将结果入栈
stack.push(result);
}
}
// 返回栈中的最后一个数据
return stack.pop();
}
/**
* 将中缀表达式转换成后缀表达式
*
* @param midExpression
* @return 后缀表达式
*/
public static String midToSuffix(String midExpression) {
// 定义两个栈,一个用于存放中间表达式,一个用于存放操作符
Stack<String> tempStack = new Stack<String>();// 用于存放中间表达式
Stack<String> operStack = new Stack<String>();// 存放操作符
// 扫描字符串
List<String> list = getListString(midExpression);
for (String item : list) {
// 遇到数字直接进tempStack
if (item.matches("\\d+")) {
tempStack.push(item);
} else {
// 如果是操作符,就和operStack栈顶的元素比较优先级
if (operStack.isEmpty()) {// 如果操作符栈为空,直接入栈
operStack.push(item);
} else {// 操作符栈不为空,就和栈顶操作符比较优先级
if (priority(item) > priority(operStack.peek())) {// 当前操作符优先级大于栈顶优先级
// 判断是不是右括号")"
if (priority(item) == 4) {// 是右括号,则将operStack出栈并将出栈操作符入栈tempStack
while (true) {
String oper = operStack.pop();
if (priority(oper) == 1) {// 遇见左括号,就停止出栈
break;
} else {// 不是左括号,就入栈tempStack
tempStack.push(oper);
}
}
} else {// 不是右括号,直接入栈operStack
operStack.push(item);
}
} else {// 小于,等于栈顶优先级
if(priority(item) == 1) { // 是左括号时,直接入栈
operStack.push(item);
}else { // 不是左括号,将栈顶操作符弹出并入栈tempStack
tempStack.push(operStack.pop());
operStack.push(item);
}
}
}
}
}
// 扫描完成后,将operStack中的操作符全部弹出到tempStack中
while (!operStack.isEmpty()) {
tempStack.push(operStack.pop());
}
// 扫描完成后,将tempStack中的字符全部弹出,其逆序就是后缀表达式
String resString = "";
while (!tempStack.isEmpty()) {
resString += tempStack.pop();
}
return new StringBuffer(resString).reverse().toString().replace("", " ").trim();
}
public static int priority(String oper) {
int res = 0;
switch (oper) {
case "(":
res = 1;
break;
case "-":
res = 2;
break;
case "+":
res = 2;
break;
case "*":
res = 3;
break;
case "/":
res = 3;
break;
case ")":
res = 4;
break;
default:
throw new RuntimeException("操作符有误!");
}
return res;
}
}