求解表达式求值问题(简洁计算器)
表达式求值
https://www.nowcoder.com/practice/c215ba61c8b1443b996351df929dc4d4?tpId=196&&tqId=37183&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking
牛客网在线编程题目
题目要求:
描述
请写一个整数计算器,支持加减乘三种运算和括号。
输入:"1+2"
输出:3
解:
分析题目
其实现步骤主要包括三大函数进行实现,这里采用的是midtransportBehind(中缀转为list)transport(中缀表达式转换为后缀表达式),caluace(计算表达式)。三个部分中缀转为list
先说一下这个函数的编写吧,其实现的原理依据就是通过ASCII码进行判断,对数字符号和非数字符号依次遍历进行放置在list结构中,先给出代码://中缀转list private List<String> midtransportBehind(String s) { //定义一个list List<String> ls = new ArrayList<String>(); int i = 0;//作为一个指针遍历 String str;//多位数拼接 char c;//作为存储的 do {//不是数字符号,数字符号的范围在48-57之间表示0-9 if( (c=s.charAt(i))< 48 || (c=s.charAt(i)) > 57 ){ ls.add(""+c); i++;//后移 }else{ str = "";//进行数字字符的拼接 while(i < s.length() && (c = s.charAt(i))>= 48 && (c = s.charAt(i))<= 57 ){ str = str+c; i++; } ls.add(str); } } while (i<s.length()); return ls; }
中缀转后缀
该部分所实现的代码主要根据采用一个栈和一个arraylist的数列表进行实现, 1、首先是定义栈和数列
//定义一个符号栈 Stack<String> stack1 = new Stack<String>(); //不需要定义一个数字栈,直接使用一个ArrayList List<String> stack2 = new ArrayList<String>();
其次是在遍历上面转化的list链表中的式子进行分情况判断:
1、若为数字-〉进入list
2、若匹配到左括号-〉进栈
3、匹配到右括号-〉进行检查栈顶的元素是否为左括号,如果不是泽则进行出栈。
4、若遇到优先级的问题需要对优先级进行栈顶与入站字符进行判断,,栈顶的元素如果高于要加入的元素,这就需要对其进行出栈进行加入队列,最后的字符进行入栈。
代码如下://中缀转后缀 private List<String> transport(List<String> ls) { //定义一个符号栈 Stack<String> stack1 = new Stack<String>(); //不需要定义一个数字栈,直接使用一个ArrayList List<String> stack2 = new ArrayList<String>(); //遍历栈 for(String eleString: ls){ if(eleString.matches("\\d+")){ stack2.add(eleString); }else if(eleString.equals("(")){ stack1.push(eleString);//进栈 }else if(eleString.equals(")")){ while(!stack1.peek().equals("(")){ stack2.add(stack1.pop()); } stack1.pop();//消除做括号 }else{ //当优先级小雨等于栈顶的优先级 while(stack1.size() != 0 && Operation.getOperation(stack1.peek()) >= Operation.getOperation(eleString)){ stack2.add(stack1.pop()); } stack1.push(eleString); } } while(stack1.size() != 0){ stack2.add(stack1.pop()); } return stack2; }
后缀表达式计算
计算表达式依据的也是对栈的操作,通过出栈和入栈进行配合进行计算取值,若检测到数字出现时,将其压入栈中,检测到字符时进行判断,并将其数据出栈进行计算,计算结果入栈,最后返回栈内结果便是最终的计算结果。private int caluace(List<String> list) { int res = 0; // TODO Auto-generated method stub Stack<String> stack = new Stack<String>(); //开始遍历 for(String eleString : list){ if(eleString.matches("\\d+")){ stack.push(eleString);//压入栈中 }else { int num1 = Integer.parseInt(stack.pop()); int num2 = Integer.parseInt(stack.pop()); if(eleString.equals("+")){ res = num1+ num2; }else if(eleString.equals("-")){ res = num2 - num1; }else if(eleString.equals("*")){ res = num1 * num2; }else if(eleString.equals("/")){ res = num2/num1; }else { throw new RuntimeErrorException(null,"运算符错误"); } //结束后进行结果压栈 stack.push(""+res); } }
return Integer.parseInt(stack.pop()); }
这里进行优先级判断的类主要如下:
class Operation{
private static int ADD = 1;
private static int SUB = 1;
private static int MUL = 2;
private static int DIV = 2;
//写一个方法范围优先级 public static int getOperation(String operation){ int result =0; switch (operation) { case "+": result = ADD; break; case "-": result = SUB; break; case "*": result = MUL; break; case "/": result = DIV; break; default: System.out.println("不存在运算符"); break; } return result; }
}
```