【九度OJ】1019【栈】

来源:互联网 发布:手机淘宝美图软件 编辑:程序博客网 时间:2024/06/07 16:05

编写一个简易计算器,简易体现在无小数,无负数,无括号运算,并且表达式中操作数和操作符是由空格分开的,处理起来比较方便。整体难度不大,只要弄清计算表达式的原理即可。

我是先将中缀表达式变为后缀表达式,再计算后缀表达式。使用栈和队列。80MS,最好的70MS。

原理:

1.中缀表达式-->后缀表达式
   操作数直接写入后缀表达式,若为操作符,其优先级小于等于栈顶元素的优先级时,弹出优先级比它大的所有操作符。
   直到该操作符优先级大于栈顶元素优先级。这时,将其压入栈中。 表达式遍历完毕时,将栈中所有元素弹出放入后缀表达式中 (先弹出的先放在后缀表达式末尾)
2.后缀表达式计算
   从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

注意最后取精度的时候用的BigDecimal


代码:

package Test1;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.math.BigDecimal;import java.util.HashMap;import java.util.LinkedList;import java.util.Queue;import java.util.Stack;import java.util.StringTokenizer;public class Test12_1019 {/** * by qr jobdu 1019 2014-8-10(11) *  * @throws IOException */public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));HashMap<String,Integer> map=new HashMap<String,Integer>();  //<操作符,优先级>map.put("#", 1);map.put("+", 2);map.put("-", 2);map.put("*", 3);map.put("/", 3);String nifixExp = ""; // 中缀表达式while (!(nifixExp = br.readLine()).equals("0")) {Stack<String> stack=new Stack<String>();  //!Java 集合类stack.push("#");  //#在栈底,优先级最低Queue<String> queue=new LinkedList<String>();  //!  // 后缀表达式StringTokenizer st = new StringTokenizer(nifixExp);  //!遍历中缀表达式String s="";while (st.hasMoreTokens()) {s = st.nextToken();if (isDigit(s)) {  //是数字queue.add(s);}else{   //是操作符String fe=stack.peek();  //只看不删int priority=map.get(s);while(priority<=map.get(fe)){queue.add(stack.pop());fe=stack.peek();  //勿忘重新赋值,指向下一个}stack.push(s);  //优先级大于栈顶元素时,入栈}}while(!stack.isEmpty()){queue.add(stack.pop());  //栈底的#也放在后缀表达式末尾了}while((s=queue.poll())!="#"){ //remove() 和 poll() 方法仅在队列为空时其行为有所不同:remove() 方法抛出一个异常,而 poll() 方法则返回 null。if(isDigit(s)){ //是数字stack.push(s);}else{ //是操作符String operand2=stack.pop();String operand1=stack.pop();stack.push(calculate(operand1,operand2,s));  //第一个操作数,第二个操作数,操作符}}//outputString result=stack.pop();  //结果,保留后两位输出//System.out.println(String.format("%2f",result));  不行,如果本身没有那么多小数位,则会报错System.out.println(new BigDecimal(result).setScale(2,BigDecimal.ROUND_HALF_UP));}}private static String calculate(String operand1, String operand2, String operator) {switch (operator.charAt(0)){case '+':return  Double.parseDouble(operand1)+ Double.parseDouble(operand2)+"";  //都要变成double,因为中间操作数可能变成doublecase '-':return  Double.parseDouble(operand1)- Double.parseDouble(operand2)+"";case '*':return  Double.parseDouble(operand1)* Double.parseDouble(operand2)+"";case '/':return  Double.parseDouble(operand1)/ Double.parseDouble(operand2)+"";  //保留两位default:return  "0";}}private static boolean isDigit(String s) {  //判断是否为数字if (!s.equals("+") && !s.equals("-") && !s.equals("*") && !s.equals("/")) {return true;}return false;}}



0 0
原创粉丝点击