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

来源:互联网 发布:sql语句求和1到50 编辑:程序博客网 时间:2024/06/06 00:39


测试地址: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);}}}


0 0