首页 > 代码库 > 表达式求值(中缀式转后缀式,后缀式求值)NYOJ53测试通过

表达式求值(中缀式转后缀式,后缀式求值)NYOJ53测试通过


测试地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=35

package calc;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Main {
	//操作符栈
	static LinkedList<String> opStack=new LinkedList<String>();
	//优先级映射
	static Map<String, Integer> priority=new HashMap<String, Integer>(){
		{
			put("(", 0);
			put(")", 0);
			put("+", 1);
			put("-", 1);
			put("*", 2);
			put("/",2);
		}
	};
	/**
	 * 中缀转后缀:
	 * 		从左到右扫描表达式
	 * 		a:若是数字直接输出
	 * 		b:若是(直接入栈
	 * 		c:若是)将栈中操作符依次退栈输出,直到遇到(为止,将(出栈丢弃
	 * 		d其他:将当前操作符的优先级小于等于栈顶操作符优先级,则将栈顶操作出栈输出,直到不小于或栈空为止;将当前操作符入栈
	 */
	public static List<String> midToAfter(String [] mid){
		LinkedList<String> after=new LinkedList<String>();
		int index=0;
		for(String ss:mid){
			if(ss.equals("=")) continue;
			if(priority.get(ss)==null){//说明是操作数
				after.add(ss);
			}else if(ss.equals("(")){
				opStack.push(ss);
			}else if(ss.equals(")")){
				while(!opStack.peek().equals("(")){//不是“(”,则输出,
					after.add(opStack.pop());
				}
				opStack.pop();//去除(
			}else {
				while(!opStack.isEmpty()&&priority.get(ss)<=priority.get(opStack.peek())){
					after.add(opStack.pop());
				}
				opStack.push(ss);
			}
		}
		while(!opStack.isEmpty()) after.add(opStack.pop());
		return after;
	}
	/**
	 * 后缀求值:从左到右扫描后缀表达式
	 * 		a:若为数字,直接入栈
	 * 		b:若为操作符,从栈中出栈两个数字,按操作符计算,再把结果入栈,注意两个操作数运算顺序
	 * 		结果:最后栈中只有一个数字,出栈即为答案
	 * @param after
	 * @return
	 */
	public static double afterValue(List<String> after){
		LinkedList<Double> number=new LinkedList<Double>();
		for(String ss:after){
			if(priority.get(ss)!=null){//是操作符,取出两个数,按操作符计算后入数字栈
				Double y=number.pop();
				Double x=number.pop();
				if(ss.equals("+")) number.push(x+y);
				else if(ss.equals("-")) number.push(x-y);
				else if(ss.equals("*")) number.push(x*y);
				else if(ss.equals("/")) number.push(x/y);
			}else{
				number.push(Double.valueOf(ss));
			}
		}
		return number.pop();
	}
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		String s;
		in.nextLine();//读书上面输入数字的那个换行
		while(n--!=0){
			//s=in.nextLine();
			s=in.nextLine();
			//将输入分离
			int pre=-1;//上一个符号的位置,当两个符号一起时:)*   应分成:*# 否则分成:#*#
			StringBuffer sb=new StringBuffer();
			for(int i=0;i<s.length();i++){
				if(s.charAt(i)!='.'&&(s.charAt(i)<'0'||s.charAt(i)>'9')){
					if(i-1==pre){ //上一个也是操作符号
						sb.append(s.charAt(i)+"#");	
					}
					else sb.append("#"+s.charAt(i)+"#");
					pre=i;//更新pre
				}else{
					sb.append(s.charAt(i));
				}
			}
			String[] split = sb.toString().split("#");
			List after=midToAfter(split);
			double ans=afterValue(after);
			System.out.printf("%.2f\n",ans);
		}
	}
}


表达式求值(中缀式转后缀式,后缀式求值)NYOJ53测试通过