【九度OJ】1019【栈】

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

我是先将中缀表达式变为后缀表达式,再计算后缀表达式。使用栈和队列。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));  //第一个操作数,第二个操作数,操作符
				}
			}
			
			//output
			String 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,因为中间操作数可能变成double
		case '-':
			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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值