一,前、中、后缀表达式
1,前缀表达式(波兰表达式):
前缀表达式: 又称波兰表达式,运算符位于表达式之前;
前缀表达式计算机求值: 从右至左扫描前缀表达式,将数字压栈,遇到运算符时,弹出两个数值,用运算符进行运算,然后在将运算结果压栈,反复直到表达式最左端,最后得到结果;如:(- * + 3 4 5 6)==》(3+4)*5-6 ,6543全部压栈,遇到+,弹出3,4得3+4=7压栈,再遇到 * 弹出7,5…
2,中缀表达式
中缀表达式: 即我们常用的数学表达式,如(3+4)*5-6,但是计算机不方便操作(数据结构与算法–第四篇(栈&模拟计算器)),所以一般都转为前、后缀表达式,多为后缀表达式;
3,后缀表达式(逆波兰表达式)
后缀表达式: 又称逆波兰表达式,与前缀表达式相似,操作符位于需要操作的数字之后,如(3+4)*5-6==》3 4 + 5 * 6 -
后缀表达式计算机求值: 从左至右扫描后缀表达式,遇到数字就压栈,遇到运算符就弹出栈顶前两个用该运算符运算,结果再入栈,重复上述直至达到表达式最右端,最后得到结果;
4,中缀转后缀表达式
转换思路:
- 初始化两个栈,运算符栈s1和存储中间结果栈s2;
- 从左至右扫描中缀表达式;
- 遇到数值时压入s2;
- 遇到运算符时,比较其与s1栈顶运算符的优先级;
4.1.如果s1为空,或栈顶运算符为左括号‘(’,则直接将次运算符入栈;
4.2.否则,若优先级比栈顶运算符高,也直接压入s1;
4.3.否则,将s1栈顶的运算符弹出压入s2,再次转到(4.1)与s1中新的栈顶运算符比较; - 遇到括号时:
5.1.如果是‘(’,直接压入s1;
5.2.如果是‘)’,则依次弹出s1栈顶的运算符,压入s2,直到遇到‘(’为止,此时直接丢弃括号; - 重复步骤2-5,直到表达式最右边;
- 将s1中的表达式依次弹出压入s2;
- 依次弹出s2的元素,结果逆序即为中缀表达式转后缀的结果;
代码实现:
public static String suffixString(List<String> suffixStringList) {
StringBuffer sb = new StringBuffer();
for (String s : suffixStringList) {
sb.append(s + " ");
}
return sb.toString().substring(0, sb.length() - 1);
}
public static List<String> toSuffixStringList(List<String> infixStringList) {
Stack<String> stack = new Stack<>();
int size = infixStringList.size();
List<String> suffixStringList = new ArrayList<>(size);
for (String s : infixStringList) {
if (s.matches("\\d+")) {
suffixStringList.add(s);
} else if ("(".equals(s)) {
stack.push(s);
} else if (")".equals(s)) {
while (!"(".equals(stack.peek())) {
suffixStringList.add(stack.pop());
}
stack.pop();//将符号栈的"("弹出
} else {
while (stack.size() != 0 && (symblo(s) <= symblo(stack.peek()))) {
suffixStringList.add(stack.pop());
}
stack.push(s);
}
}
while (stack.size() != 0) {
suffixStringList.add(stack.pop());
}
return suffixStringList;
}
public static int symblo(String symbol) {
int result = 0;
switch (symbol) {
case "+":
case "-":
result = 1;
break;
case "*":
case "/":
result = 2;
break;
default:
break;
}
return result;
}
5,逆波兰计算器
package com.stack;
import sun.awt.geom.AreaOp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
/**
* @param
* @Author: AaNeei
* @Date: 2019/6/14 22:37
* @Description: 游学网
* @throws:
*/
public class ReversePolishCalculator {
public static void main(String[] args) {
String infixNotation = "111+((2+3)*4)-5";
List<String> stringList = infixToStringList(infixNotation);
List<String> suffixStringList = toSuffixStringList(stringList);
String s = suffixString(suffixStringList);
System.out.println(stringList + "===>" + suffixStringList + "===>" + s);
List<String> string = getListString(s);
int calculate = calculate(string);
System.out.println(infixNotation + "=" + calculate);
}
public static String suffixString(List<String> suffixStringList) {
StringBuffer sb = new StringBuffer();
for (String s : suffixStringList) {
sb.append(s + " ");
}
return sb.toString().substring(0, sb.length() - 1);
}
public static List<String> toSuffixStringList(List<String> infixStringList) {
Stack<String> stack = new Stack<>();
int size = infixStringList.size();
List<String> suffixStringList = new ArrayList<>(size);
for (String s : infixStringList) {
if (s.matches("\\d+")) {
suffixStringList.add(s);
} else if ("(".equals(s)) {
stack.push(s);
} else if (")".equals(s)) {
while (!"(".equals(stack.peek())) {
suffixStringList.add(stack.pop());
}
stack.pop();//将符号栈的"("弹出
} else {
while (stack.size() != 0 && (symblo(s) <= symblo(stack.peek()))) {
suffixStringList.add(stack.pop());
}
stack.push(s);
}
}
while (stack.size() != 0) {
suffixStringList.add(stack.pop());
}
return suffixStringList;
}
public static int symblo(String symbol) {
int result = 0;
switch (symbol) {
case "+":
case "-":
result = 1;
break;
case "*":
case "/":
result = 2;
break;
default:
break;
}
return result;
}
public static List<String> infixToStringList(String infixNotation) {
int length = infixNotation.length();
List<String> stringList = new ArrayList<>(length);
int i = 0;
char ch;
do {
if ((ch = infixNotation.charAt(i)) < 48 || (ch = infixNotation.charAt(i)) > 57) {
stringList.add(ch + "");
i++;
} else {
StringBuffer sb = new StringBuffer("");
while (i < length && (ch = infixNotation.charAt(i)) >= 48 && (ch = infixNotation.charAt(i)) <= 57) {
sb.append(ch + "");
i++;
}
stringList.add(sb.toString());
}
} while (i < length);
return stringList;
}
public static int calculate(List<String> notation) {
Stack<String> stack = new Stack<>();
for (String s : notation) {
if (s.matches("\\d+")) {
stack.push(s);
} else {
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int result = 0;
switch (s) {
case "+":
result = num1 + num2;
break;
case "-":
result = num2 - num1;
break;
case "*":
result = num1 * num2;
break;
case "/":
result = num2 / num1;
break;
default:
break;
}
stack.push("" + result);
}
}
return Integer.parseInt(stack.pop());
}
//reversePolishNotation用 空格隔开
public static List<String> getListString(String reversePolishNotation) {
String[] array = reversePolishNotation.split(" ");
return Arrays.asList(array);
}
}