目录
一、需求
A:中缀表达式转后缀表达式
例:1+((2+3)*4)-5
二、字符串扫描法
-
思路分析
A:定义两个栈,运算符栈S1和储存中间结果栈S2;
B:从左至右依次扫描字符串,遇到数字就入栈S2;
C:扫描到运算符
a:栈S1为空的话,直接入栈;
b:栈S1非空,则与S1栈顶元素比较优先级,若当前运算符
优先级高,则入栈,否则弹出S1栈顶元素并入栈S2,继
续比较优先级;
D:扫描到左括号,直接入栈S1;
E:扫描到右括号,将S1中的左括号上面的所有元素全部出栈,并
压入栈S2,最后出栈左括号;
F:表达式扫描完毕后,将S1中的元素弹出并压入栈S2;
G:栈S2自栈底向栈顶的元素,即为后缀表达式;
-
图解
-
代码实现
package cn.itcast_04;
import java.util.Stack;
/*
* 需求:中缀表达式转后缀表达式
* 例:1+((2+3)*4)-5----输出:1 2 3 + 4 * + 5 -
*
* 分析:
* A:定义两个栈,运算符栈S1和储存中间结果栈S2;
* B:从左至右依次扫描字符串,遇到数字就入栈S2;
* C:扫描到运算符
* a:栈S1为空的话,直接入栈;
* b:栈S1非空,则与S1栈顶元素比较优先级,若当前运算符
* 优先级高,则入栈,否则弹出S1栈顶元素并入栈S2,继
* 续比较优先级;
* D:扫描到左括号,直接入栈S1;
* E:扫描到右括号,将S1中的左括号上面的所有元素全部出栈,并
* 压入栈S2,最后出栈左括号;
* F:表达式扫描完毕后,将S1中的元素弹出并压入栈S2;
* G:栈S2自栈底向栈顶的元素,即为后缀表达式;
*/
public class MidToBack {
public static void main(String[] args) {
// 给出字符串
String expression = "1+((2+3)*4)-5";
// 定义运算符栈S1和栈S2
Stack<String> s1 = new Stack<String>();
Stack<String> s2 = new Stack<String>();
// 用于保存多位数
String keepNum = "";
// 对字符串进行扫描
for (int i = 0; i < expression.length(); i++) {
String item = expression.substring(i, i + 1);
if (isOper(item.charAt(0))) {
if (s1.empty()) {
s1.push(item);
} else {
while (!s1.empty() && priority(item.charAt(0)) <= priority(s1.peek().charAt(0))) {
String temp = s1.pop();
s2.push(temp);
}
s1.push(item);
}
} else if (item.equals("(")) {
s1.push(item);
} else if (item.equals(")")) {
while (!s1.empty() && !s1.peek().equals("(")) {
String temp = s1.pop();
s2.push(temp);
}
s1.pop();// 左括号扔掉
} else {
// 是数字
keepNum += item;
if (i == expression.length() - 1) {
s2.push(keepNum);
} else {
char ch = expression.substring(i + 1, i + 2).charAt(0);
if (isOper(ch) || ch == ')') {
s2.push(keepNum);
keepNum = "";
}
}
}
}
// 将S1中的元素弹出并压入S2
while (!s1.empty()) {
String temp = s1.pop();
s2.push(temp);
}
System.out.println("s2" + s2);
// 遍历栈S2存放到字符串中
String backExpression = "";
String[] chs = new String[s2.size()];
int index = 0;
while (!s2.isEmpty()) {
chs[index++] = s2.pop();
}
// 遍历数组
for (index = chs.length - 1; index >= 0; index--) {
backExpression += chs[index];
backExpression += " ";
}
// 去掉最后的空格
System.out.println("后缀表达式为:" + backExpression.trim());
}
// 判断字符是否为运算符
public static boolean isOper(int ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
// 自定义运算符优先级
public static int priority(int ch) {
if (ch == '+' || ch == '-') {
return 0;
} else if (ch == '*' || ch == '/') {
return 1;
} else {
return -1;// 这里左括号为保证能够在堆栈里,优先级设为最低
}
}
}
三、使用ArrayList优化
package cn.itcast_04;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/*
*需求:
* A:1+((2+3)*4)-5 ----> 1 2 3 + 4 * + 5 -
*
*分析:
* A:扫描字符串不方便,故采用ArrayList来存放字符串;
* B:将ArrayList传递给一个方法,遍历ArrayList,配合栈完成计算
*/
public class MidToBack2 {
public static void main(String[] args) {
// 定义给逆波兰表达式
String expression = "1+((2+3)*4)-5";
List<String> list = toMidList(expression);
List<String> backExpression = midToBack(list);
// 遍历list
System.out.println(list);
System.out.println(backExpression);
}
// 将中缀表达式转为对应的List
public static List<String> toMidList(String expression) {
List<String> ls = new ArrayList<String>();
int i = 0;
String keepNum;
char c;
do {
if ((c = expression.charAt(i)) < 48 || (c = expression.charAt(i)) > 57) {
ls.add("" + c);
i++;
} else {
keepNum = "";
while (i < expression.length() && (c = expression.charAt(i)) >= 48
&& (c = expression.charAt(i)) <= 57) {
keepNum += c;
i++;
}
ls.add(keepNum);
}
} while (i < expression.length());
return ls;
}
// 转换为ArrayList [1,2,3,+,4,*,+,5,-]
public static List<String> midToBack(List<String> ls) {
// 定义符号栈和储存结果的s2
Stack<String> s1 = new Stack<String>();
List<String> s2 = new ArrayList<String>();// 只管存储就好了
// 遍历ls
for (String item : ls) {
// 数字则入s2
if (item.matches("\\d+")) {
s2.add(item);
} else if (item.equals("(")) {
s1.add(item);
} else if (item.equals(")")) {
while (!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();
} else {
while (s1.size() != 0 && priority(s1.peek().charAt(0)) >= priority(item.charAt(0))) {
s2.add(s1.pop());
}
s1.push(item);
}
}
// 将s1剩余运算符加入s2
while (s1.size() != 0) {
s2.add(s1.pop());
}
return s2;
}
// 自定义运算符优先级
public static int priority(int ch) {
if (ch == '+' || ch == '-') {
return 0;
} else if (ch == '*' || ch == '/') {
return 1;
} else {
return -1;// 这里左括号为保证能够在堆栈里,优先级设为最低
}
}
}