将一个大问题分解成一个个小问题来求解,就不会被难题的复杂度给吓倒。
代码实现:
核心函数:
/**
* 写一个整数计算器,支持加减乘三种运算和括号
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
public int solve (String s) {
// write code here
// 初始化运算符信息
initOpMap();
// 去掉字符串里的空格
s = s.trim();
itemList = new LinkedList<>();
stack = new LinkedList<>();
char[] chars = s.toCharArray();
// 生成后缀表达式
toPostfixExpression(chars);
// 返回根据后缀表达式得到的计算结果
return computeByPostfixExpression();
}
整体实现:
/**
* 简单计算器的实现
* @author 49367
* @date 2021/4/12 22:31
*/
public class ComputeExpression {
// 分隔符枚举类
private enum Delimiter {
LEFT_BRACKET("("), RIGHT_BRACKET(")");
private String type; // 分隔符的类型
private Delimiter(String s){
this.type = s;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
// 运算符枚举类
private enum Operator {
ADD("+", 0), SUB("-", 0), MUL("*", 1);
private String type; // 运算符的类型
private int priority; // 运算符的优先级
private Operator(String s, int priority){
this.type = s;
this.priority = priority;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
}
// key为运算符,val为优先级
private HashMap<String, Integer> opMap;
/**
* 初始化运算符及其优先级信息
*/
private void initOpMap(){
opMap = new HashMap<>();
for (Operator op : Operator.values()) {
opMap.put(op.getType(), op.getPriority());
}
}
// 表达式各项的线性表
private LinkedList<String> itemList;
// 操作栈
private Deque<String> stack;
/**
* 写一个整数计算器,支持加减乘三种运算和括号
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
public int solve (String s) {
// write code here
// 初始化运算符信息
initOpMap();
// 去掉字符串里的空格
s = s.trim();
itemList = new LinkedList<>();
stack = new LinkedList<>();
char[] chars = s.toCharArray();
// 生成后缀表达式
toPostfixExpression(chars);
// 返回根据后缀表达式得到的计算结果
return computeByPostfixExpression();
}
/**
* 生成后缀表达式,保存在线性表itemList中
* @param chars
*/
private void toPostfixExpression(char[] chars) {
int i = 0, len = chars.length;
while (i < len){
if(!Character.isDigit(chars[i])){
// chars[i]为非数字字符,可以是运算符,也可以是分隔符(括号)
itemIsNonDigit(String.valueOf(chars[i++]));
continue;
}
// 如果是数字,先生成数字的字符串,然后直接加入到线性表中
StringBuilder sb = new StringBuilder();
while (i < len && Character.isDigit(chars[i]))
sb.append(chars[i++]);
itemList.addLast(sb.toString());
}
// 将操作栈剩余的item都弹出到itemList中
while (!stack.isEmpty())
itemList.addLast(stack.removeLast());
}
/**
* 当item不是数字时,它可以是运算符,也可以是分隔符(括号)
* @param item
*/
private void itemIsNonDigit(String item) {
// 该项是运算符
if(opMap.containsKey(item))
itemIsOp(item);
// 该项是分隔符(即括号)
else
itemIsDelimiter(item);
}
/**
* 当item是分隔符(在本题中即括号)时
* @param item
*/
private void itemIsDelimiter(String item) {
// 是左括号 "("
if(Delimiter.LEFT_BRACKET.getType().equals(item))
stack.addLast(item);
// 是右括号 ")"
else if(Delimiter.RIGHT_BRACKET.getType().equals(item)){
// 弹出括号之间的所有item并加入到线性表中(不包括括号)
while (!stack.isEmpty() && !Delimiter.LEFT_BRACKET.getType().equals(stack.peekLast())){
itemList.addLast(stack.removeLast());
}
// 弹出左括号
stack.removeLast();
}
}
/**
* 当item是运算符时
* @param item
*/
private void itemIsOp(String item) {
String peek;
int itemPriority = opMap.get(item);
// 操作栈顶优先级更高才出栈,加入到线性表中,
while (!stack.isEmpty() && opMap.containsKey(peek = stack.peekLast())
&& opMap.get(peek) >= itemPriority)
itemList.addLast(stack.removeLast());
stack.addLast(item);
}
/**
* 根据itemList所代表的后缀表达式计算结果,前提是必须保证后缀表达式是正确的
* @return
*/
private int computeByPostfixExpression() {
// 操作数栈,存放将要被运算的数字
Deque<Integer> stack = new LinkedList<>();
for (String item : itemList) {
// item是运算符
if (opMap.containsKey(item)){
int num2 = stack.removeLast();
int num1 = stack.removeLast();
stack.addLast(compute(num1, num2, item));
}
// item是数字,直接加到操作数栈中
else
stack.addLast(Integer.parseInt(item));
}
return stack.removeLast();
}
/**
* 计算
* @param num1
* @param num2
* @param item 运算符
* @return
*/
private int compute(int num1, int num2, String item) {
if(Operator.ADD.getType().equals(item))
return num1 + num2;
if(Operator.SUB.getType().equals(item))
return num1 - num2;
if(Operator.MUL.getType().equals(item))
return num1 * num2;
return 0;
}
}