借助栈实现表达式求值
表达式求值
http://www.nowcoder.com/questionTerminal/9566499a2e1546c0a257e885dfdbf30d
提交了7次才全部通过。。
代码还有很多可以优化的地方,如下,可能有考虑不全的情况,欢迎指正~
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str = "";
while ((str = reader.readLine()) != null){
String pattern = "[^\\d|()()*+\\-/]";
if (!Pattern.compile(pattern).matcher(str).find()){
String[] expressions = str.split("");
// 转换表达式
final List<Object> suffix = infixToSuffix(expressions);
// 计算结果
System.out.println(evaluate(suffix));
} else System.out.println(-1);
}
reader.close();
}
/**
* 执行计算
* @param suffix 后缀表达式
* @return 返回Integer结果
*/
public static Integer evaluate(List<Object> suffix){
if (null == suffix || suffix.size() == 0) return -1;
Stack<Integer> nums = new Stack<>(); // 存储数字
for (int i = 0; i < suffix.size(); i++) {
if (suffix.get(i) instanceof Integer) {
// 遇到数字则入栈
nums.push(Integer.parseInt(String.valueOf(suffix.get(i))));
} else if (suffix.get(i) instanceof String && nums.size() >= 2){ // 遇到运算符,执行运算
switch (String.valueOf(suffix.get(i))){
case "+":
nums.push(nums.pop() + nums.pop());
break;
case "-":
Integer pop1 = nums.pop();
Integer pop2 = nums.pop();
nums.push(pop2 - pop1);
break;
case "*":
nums.push(nums.pop() * nums.pop());
break;
case "/":
Integer denominator = nums.pop();
Integer numerator = nums.pop();
if (denominator == 0) return -1;
else nums.push(numerator / denominator);
break;
}
} else return -1;
}
Integer res = 0;
while (!nums.isEmpty()) {
res = nums.pop();
}
return res;
}
/**
* 中缀表达式转后缀表达式(逆波兰表达式)
* @param expressions 表达式字符串数组
* @return 返回后缀表达式
*/
public static List<Object> infixToSuffix(String[] expressions){
if (null == expressions || expressions.length == 0) return null;
Stack<String> stack = new Stack<>();
StringBuilder builder = new StringBuilder();
List<Object> result = new ArrayList<>();
for (int i = 0; i < expressions.length; i++) {
if (i == 0 && !Character.isDigit(expressions[0].charAt(0)) &&
!expressions[0].equals("(") && !expressions[0].equals("(")){
builder.append(expressions[0]);
continue;
}
if (Character.isDigit(expressions[i].charAt(0))){
// 遇到数字,拼接起来,还原原数
builder.append(expressions[i]);
} else {
if (builder.length() != 0){
// 将还原后的数字存起来
result.add(Integer.parseInt(builder.toString()));
builder.delete(0, builder.length());
}
switch (expressions[i]){
case "+":
case "-":
if (expressions[i].equals("-") && i != 0 && (expressions[i - 1].equals("(") || expressions[i - 1].equals("(")))
builder.append(expressions[i]);
// +和-优先级相同且最低,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈
else if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("("))
stack.push(expressions[i]);
else {
// 当栈不为空且栈顶元素不是左括号时,将栈元素依次输出,直到栈为空,再压入当前运算符
while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("("))
result.add(stack.pop());
stack.push(expressions[i]);
}
break;
case "*":
case "/":
// *和/优先级相同且大于+和-,小于括号,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈
if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("("))
stack.push(expressions[i]);
else {
// 当栈不为空且栈顶元素不是左括号,同时栈顶元素优先级大于等于自己时,将栈元素依次输出,直到栈为空,再压入当前运算符
while (!stack.isEmpty() && !stack.peek().equals("+") && !stack.peek().equals("-")
&& !stack.peek().equals("(") && !stack.peek().equals("("))
result.add(stack.pop());
stack.push(expressions[i]);
}
break;
case "(":
case "(":
// 遇到左括号直接入栈
stack.push(expressions[i]);
break;
case ")":
case ")":
// 遇到右括号,当栈不为空且栈顶元素不是左括号时,输出栈元素,直到栈为空或者遇到了左括号。注意这里不执行入栈操作
while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("("))
result.add(stack.pop());
// 因为遇到左括号而停止出栈时,需要将左括号出栈
if (!stack.isEmpty())
stack.pop();
break;
}
}
}
// 先清空builder
if (builder.length() != 0){
result.add(Integer.parseInt(builder.toString()));
builder.delete(0, builder.length());
}
// 最后一步,将栈中剩余元素全部输出
while (!stack.isEmpty())
result.add(stack.pop());
return result;
}
}