前言
java 菜鸟,正在学习java数据结构与算法;
根据中缀表达式转后缀表达式的规则、后缀表达式计算(逆波兰表达式)的规则,代码进行了实现。
有不当之处,还请提出改正
public class 逆波兰计算器 {
public static void main(String[] args) {
String str = "231 + 30*4 + (50 * 6 + 71) / 8";
String resultString = stringToPolandNotation(str);
System.out.println("resultString = " + resultString);
//resultString = 231 30 4 * + 50 6 * 71 + 8 / +
int resultNum = polandCaculator(resultString);
System.out.println("resultNum = " + resultNum);
//resultNum = 397
}
/**
* 从左至右扫描表达式,遇到数字的时候,将数字压入堆栈;
* 遇到运算符的时候,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素和栈顶元素),并将结果入栈;
* 重复 上述过程直到表达式最右端,最后运算得出的值即为表达式的结果;
*
* @param str 逆波兰表达式字符串
* @return
*/
private static int polandCaculator(String str) {
Stack<Integer> numStack = new Stack<>();
int result = Integer.MIN_VALUE;
int num = Integer.MIN_VALUE;
for (int i = 0; i < str.length(); i++) {
char operChar = str.charAt(i);
if (i == str.length() - 1) {
if (isOper(operChar)) {
int num1 = numStack.pop();
int num2 = numStack.pop();
result = calculate(num1, num2, operChar);
}
} else {
if (operChar != ' ') {
if (isNumber(operChar)) {
if (num == Integer.MIN_VALUE) {
num = operChar - '0';
} else {
num = num * 10 + operChar - '0';
}
}
if (isOper(operChar)) {
int num1 = numStack.pop();
int num2 = numStack.pop();
int tempResult = calculate(num1, num2, operChar);
numStack.push(tempResult);
}
} else {
if (num != Integer.MIN_VALUE) {
numStack.push(num);
num = Integer.MIN_VALUE;
}
}
}
}
return result;
}
private static int calculate(int num1, int num2, char operChar) {
if (operChar == '+') return num1 + num2;
if (operChar == '-') return num2 - num1;
if (operChar == '*') return num1 * num2;
if (operChar == '/') return num2 / num1;
return 0;
}
/**
* 中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
* 转换过程需要用到栈,具体过程如下:
* 1. 如果遇到操作数,我们就直接将其输出。
* 2. 如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
* 3. 如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
* 4. 如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。
* 弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
* 5. 如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
*
* @param str 需要转换的中缀表达式
*/
private static String stringToPolandNotation(String str) {
StringBuilder builder = new StringBuilder();
Stack<Character> charStack = new Stack<>();
int num = Integer.MIN_VALUE;
for (int i = 0; i < str.length(); i++) {
char operChar = str.charAt(i);
if (i == str.length() - 1) {
if (isNumber(operChar)) {
builder.append(operChar).append(" ");
} else {
if (num != Integer.MIN_VALUE) {
builder.append(num).append(" ");
num = Integer.MIN_VALUE;
}
}
while (!charStack.isEmpty()) {
builder.append(charStack.pop()).append(" ");
}
} else {
if (operChar != ' ') {
if (isNumber(operChar)) {
if (num == Integer.MIN_VALUE) {
num = operChar - '0';
} else {
num = num * 10 + operChar - '0';
}
}
if (isOper(operChar)) {
if (num != Integer.MIN_VALUE) {
builder.append(num).append(" ");
num = Integer.MIN_VALUE;
}
if (charStack.isEmpty()) {
charStack.push(operChar);
} else {
if (operChar == ')') {
while (charStack.size() != 0 && charStack.get(charStack.size() - 1) != '(') {
builder.append(charStack.pop()).append(" ");
}
if (charStack.size() != 0 && charStack.get(charStack.size() - 1) == '(') {
charStack.pop();
}
} else if (operChar == '(') {
charStack.push(operChar);
} else if (getPriority(charStack.get(charStack.size() - 1)) < getPriority(operChar)) {
charStack.push(operChar);
} else {
while (charStack.size() != 0 && getPriority(charStack.get(charStack.size() - 1)) >= getPriority(operChar)
&& charStack.get(charStack.size() - 1) != '(') {
builder.append(charStack.pop()).append(" ");
}
charStack.push(operChar);
}
}
}
}
}
}
return builder.toString().trim();
}
private static int getPriority(char c) {
if (c == '+' || c == '-') return 1;
if (c == '*' || c == '/') return 2;
if (c == '(' || c == ')') return 3;
return Integer.MIN_VALUE;
}
private static boolean isNumber(char c) {
return c >= '0' && c <= '9';
}
private static boolean isOper(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
}
}