- 中缀表达式转后缀表达式
遍历中缀表达式中的数字和符号:
- 对于数字:直接输出
- 对于符号:
- 左括号:进栈
- 运算符号:与栈顶符号进行优先级比较
- 若栈顶符号优先级低:此符号进栈
(默认栈顶若是左括号,左括号优先级最低)
- 若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
- 右括号:将栈顶符号弹出并输出,直到匹配左括号,将左括号和右括号同时舍弃
遍历结束:将栈中的所有符号弹出并输出
- 基于后缀表达式运算
遍历后缀表达式中的数字和符号
-
- 对于数字:进栈
- 对于符号:
- 从栈中弹出右操作数
- 从栈中弹出左操作数
- 根据符号进行运算
- 将运算结果压入栈中
遍历结束:栈中的唯一数字为计算结果
package com.lg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Computer {
static HashMap<String, Integer> leveMap = new HashMap<>();
static {
leveMap.put("(", 0);
leveMap.put("+", 1);
leveMap.put("-", 1);
leveMap.put("*", 2);
leveMap.put("/", 2);
leveMap.put("%", 2);
leveMap.put("log", 3);
leveMap.put("^", 4);
}
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String readLine = bufferedReader.readLine();
Queue<String> midleTolater = midleTolater(readLine);
double computerBymidle = computerBymidle(midleTolater);
System.out.println(computerBymidle);
}
/**
* 中缀表达式计算 遍历中缀表达式 数字直接入栈 遇到算数表达式 先弹出右操作数 再弹出左操作数 将计算结果压栈
*
* 遍历结束:栈中的唯一数字为计算结果
*
* @param queue
* @return
*/
public static double computerBymidle(Queue<String> queue) {
Stack<Double> stack = new Stack<>();
queue.forEach(r -> {
if (isNumber(r)) {
stack.push(Double.parseDouble(r));
} else {
Double right = stack.pop();
Double left = stack.pop();
if ("+".equals(r)) {
stack.push(left + right);
} else if ("-".equals(r)) {
stack.push(left - right);
} else if ("*".equals(r)) {
stack.push(left * right);
} else if ("/".equals(r)) {
stack.push(left * right);
} else if ("^".equals(r)) {
stack.push(Math.pow(left, right));
} else if ("%".equals(r)) {
stack.push(left % right);
}
}
});
return stack.pop();
}
/**
* 中缀表达式转后缀表达式 遍历中缀表达式中的数字和符号:
* 对于数字:直接输出 对于符号:
* 左括号:进栈 运算符号:与栈顶符号进行优先级比较
* 若栈顶符号优先级低:
* 此符号进栈 (默认栈顶若是左括号,左括号优先级最低)
* 若栈顶符号优先级不低:
* 将栈顶符号弹出并输出,之后进栈
* 右括号:将栈顶符号弹出并输出,直到匹配左括号,
* 将左括号和右括号同时舍弃
*
* 遍历结束:将栈中的所有符号弹出并输出
*
* @param str
* @return
*/
public static Queue<String> midleTolater(String str) {
// 算数表达式数字与字符分割
LinkedList<String> queue = new LinkedList<>();
int start = 0;
for (int i = 0; i < str.length(); i++) {
if (!isNumber(str.charAt(i))) {
if (start != i)
queue.add(str.substring(start, i));
queue.add(str.substring(i, i + 1));
start = i + 1;
}else if(isNumber(str.substring(i))) {
queue.add(str.substring(i));
break;
}
}
queue.forEach(r -> System.out.println(r));
// 中缀表达式转后缀表达式
// 1、数字直接输出
// 2、左括号直接入栈
// 3、栈顶的优先级低直接入栈
// 4、栈顶的优先级高 将栈顶符号弹出并输出,之后进栈
// 5、右括号,栈顶元素弹出知道遇见右括号
// 遍历结束:将栈中的所有符号弹出并输出
Queue<String> laterString = new LinkedList<>();
Stack<String> stack = new Stack<>();
for (String element : queue) {
if (isNumber(element)) {
laterString.offer(element);
continue;
}
if ("(".equals(element)) {
stack.push(element);
continue;
}
if (")".equals(element)) {
while (!stack.isEmpty()) {
String pop = stack.pop();
if ("(".equals(pop)) {
break;
}
laterString.offer(pop);
}
continue;
}
if (stack.isEmpty() || compareleve(element, stack.peek())) {
stack.push(element);
} else {
laterString.add(stack.pop());
stack.add(element);
}
}
while (!stack.isEmpty()) {
laterString.add(stack.pop());
}
laterString.forEach(r->System.out.print(","+r));
return laterString;
}
public static boolean compareleve(String s1, String s2) {
return leveMap.get(s1).compareTo(leveMap.getOrDefault(s2, 1)) >= 0;
}
public static boolean isNumber(char c) {
return Character.isDigit(c) || '.' == c;
}
public static boolean isNumber(String ss) {
try {
Double.parseDouble(ss);
return true;
} catch (Exception e) {
// TODO: handle exception
return false;
}
}
}