第1题: 算术表达式里面括号是否匹配,如 3+{2(5*3-1)-[1+(3-5)]}匹配,3+ 2(5*3-1)-[1+(3-5)]} 不匹配。
package com.sheepmu.text; import java.util.Stack; /* 算术表达式里面括号是否匹配,如 3+{2(5*3-1)-[1+(3-5)]}匹配,3+ 2(5*3-1)-[1+(3-5)]} 不匹配。 * * 思路:出现的右括号需与离他最近的左括号配对!! * 遇到左括号入栈,越到右括号时:若栈不为空且和栈顶相同,则栈顶出栈;否则直接突出方法返回空。如果前面没有直接退出方法,则最后判断栈是否为空。 * @author sheepmu */ public class Stack_KuoHao { public static void main(String[] args){ System.out.println(isMach("(3+( 5*3-1)- [1+(3-5)]}")); } public static boolean isMach(String input ){ final char LEFT_S='('; final char LEFT_M='['; final char LEFT_L='{'; final char RIGHT_S=')'; final char RIGHT_M=']'; final char RIGHT_L='}'; Stack<Character> stack=new Stack<Character>(); int len=input .length(); char[] str_c=new char[len]; for(int i=0;i<len;i++) str_c[i]= input .charAt(i) ; for(int i=0;i<len;i++){ switch( str_c[i]){ case LEFT_S: case LEFT_M: case LEFT_L: stack.push( str_c[i]); System.out.println("进栈字符--> "+str_c[i]); break; case RIGHT_S: if(!stack.isEmpty()&&stack.peek()==LEFT_S){ System.out.println("出栈字符-s-> "+str_c[i]); stack.pop();} else //如果1.栈为空;2.栈不为空但是与栈顶不匹配! return false;//这个return直接退出方法。 break; case RIGHT_M: if(!stack.isEmpty()&&stack.peek()==LEFT_M) { System.out.println("出栈字符-m-> "+str_c[i]); stack.pop(); } else return false; break; case RIGHT_L: if(!stack.isEmpty()&&stack.peek()==LEFT_L) { System.out.println("出栈字符-l-> "+str_c[i]); stack.pop();} else return false; break; } } return stack.isEmpty(); //若前面没有return方法,则一直执行到最后并执行此方法。 } }
第2题:计算 3.8/2+222/(23-21)-45*2
package com.sheepmu.text; import java.util.ArrayList; import java.util.Stack; /* 计算 3.8/2+222/(23-21)-45*2 * 思路:1.中缀表达式--->后缀表达式 * 2.计算后缀表达式。 * @author sheepmu */ public class Stack_KuoHao { enum OperatorEnum{ add("+"), sub("-"), mul("*"), div("/"), leftkh("("), rightkh(")");//最后一个必须是分号。 private String value; public String getValue(){ return value; } OperatorEnum(String s){ value=s; } } public static void main(String[] args){ String s0="3.8/2+222/(23-21)-45*2"; System.out.println("原表达式---> "+s0); ArrayList<String> list_in=toArray(s0); System.out.println("中缀表达式ArrayList---> "+ list_in); Stack<String> stack_post= toPostfix(list_in); System.out.println("后缀表达式栈---> "+ stack_post); double result=calculatePost(stack_post); System.out.println("结果---> "+ result); } public static ArrayList<String> toArray(String input){//用ArrayList和数组相比的好处 int len=input.length(); ArrayList<String> list=new ArrayList<String>(); for(int i=0;i<len;){//!!!!!不能直接i++,因为不是每个字符为一个,因为数字可能多位数。!!!!! String ch=String.valueOf(input.charAt(i)); if(ch.equals(OperatorEnum.add.getValue())||ch.equals(OperatorEnum.sub.getValue())|| ch.equals(OperatorEnum.mul.getValue())||ch.equals(OperatorEnum.div.getValue())|| ch.equals(OperatorEnum.leftkh.getValue())||ch.equals(OperatorEnum.rightkh.getValue())){ list.add(ch);//如果遇到操作符则直接放入数组中, i++; } else{//如果非操作符,则就要判断这个数有几位数,因为不全是个位数,可能是多位数或者带有小数点。 int end=getEnd(input, i); list.add(input.substring(i, end)) ; i=end; } } return list; } public static int getEnd(String s,int i){ int result_end=i; for(int j=i;j<s.length();j++){ String ch=String.valueOf(s.charAt(j)); if(ch.equals(OperatorEnum.add.getValue())||ch.equals(OperatorEnum.sub.getValue())|| ch.equals(OperatorEnum.mul.getValue())||ch.equals(OperatorEnum.div.getValue())|| ch.equals(OperatorEnum.leftkh.getValue())||ch.equals(OperatorEnum.rightkh.getValue())){ result_end=j; break;//一旦遇到操作符就说明这个数结束,跳出循环。 } else if(j==s.length()-1){// !!!!!!!!!!!!!!!!若没有遇到操作符,即最后一个数!!!!!!!!!! result_end=s.length();//上面一定是s.length()-1,这儿一定是= s.length();不然会导致上面循环结束不了。 } } return result_end; } public static Stack<String> toPostfix(ArrayList<String> infix){ Stack<String> stack=new Stack<String>();//放操作符的栈 Stack<String> stack_post=new Stack<String>();//把后缀表达式存在栈里比较好,方便后面运算。 int len=infix.size(); for(int i=0;i<len;i++){ if(infix.get(i).equals(OperatorEnum.leftkh.getValue())){//若果是反括号;直接进操作符栈 stack.push(infix.get(i)); } else if(infix.get(i).equals(OperatorEnum.add.getValue())||infix.get(i).equals(OperatorEnum.sub.getValue())|| infix.get(i).equals(OperatorEnum.mul.getValue())||infix.get(i).equals(OperatorEnum.div.getValue())){ //若是加减乘除,则先判断操作符栈是否为空,否则比较运算级别。若扫描到的比操作符栈顶的低,操作符栈顶出来, //继续比较出了栈顶后的新栈顶是否比扫描到的高或等!!!while~~~~ if(!stack.isEmpty()){//栈不为空则比较 if(compare(stack.peek(),infix.get(i))){ //若栈顶>=扫描到的 !!!应该是while而不是if,因为有可能连着几个都比他高 while(!stack.isEmpty()&&compare(stack.peek(),infix.get(i)))// !!!!!!!!stack.isEmpty() !!!!!!!!!!!!! stack_post.push(stack.pop()); stack.push(infix.get(i));} else if(!compare(stack.peek(),infix.get(i))) stack.push(infix.get(i)); } else{//栈为空则直接进栈 !!!!!!!!!!! stack.push(infix.get(i)); } } else if(infix.get(i).equals(OperatorEnum.rightkh.getValue())){//如果扫描到右括号 if(!stack.isEmpty()){ while(!stack.peek().equals(OperatorEnum.leftkh.getValue())){ stack_post.push(stack.pop()) ; } stack.pop();//把左括号弹出栈,不要了。 } } else {//非运算符 stack_post.push(infix.get(i)); } } if(!stack.isEmpty()){//若果读完了栈中还有运算符,这一个个的出栈并加到后缀表达式中 while(!stack.isEmpty()) stack_post.push(stack.pop()); } System.out.println("临时存放中缀数组操作符的栈---->"+stack); return stack_post; } public static boolean compare(String stackpeek,String ch){ if(stackpeek.equals(OperatorEnum.mul.getValue())||stackpeek.equals(OperatorEnum.div.getValue())){ if(ch.equals(OperatorEnum.add.getValue())||ch.equals(OperatorEnum.sub.getValue())|| ch.equals(OperatorEnum.mul.getValue())||ch.equals(OperatorEnum.div.getValue())){ return true;//栈顶等级>=扫描到的元素----->把栈顶弹出并放到后缀表达式中,扫描到的进栈 } } if(stackpeek.equals(OperatorEnum.add.getValue())||stackpeek.equals(OperatorEnum.sub.getValue())){ if(ch.equals(OperatorEnum.add.getValue())||ch.equals(OperatorEnum.sub.getValue())) return true; } return false; } /** * 中缀栈计算思路:1.建个新栈存放中缀表达式栈中遍历到的操作数,若遍历到的是操作数直接放进新栈;若遍历到操作符,则取出 * 新栈中的两个栈顶元素执行遍历到的操作符的运算,并把计算结果放到新栈顶,原中缀表达式栈继续遍历。 * 最后新栈表达式中的那唯一的一个数字即最后答案 */ public static double calculatePost(Stack<String> postfix){ Stack<String> newStack=new Stack<String>(); for(String s:postfix){ if(s.equals(OperatorEnum.add.getValue())||s.equals(OperatorEnum.sub.getValue())|| s.equals(OperatorEnum.mul.getValue())||s.equals(OperatorEnum.div.getValue())){ String p=s; String d2= newStack.pop() ; String d1= newStack.pop() ; double result_temp=caltwo(d1,d2,p); newStack.push(result_temp+""); } else{//读到的是数据 newStack.push(s); } } return Double.valueOf(newStack.pop()); } public static double caltwo(String s1,String s2,String perator){ double result=0; double d1=Double.valueOf(s1); double d2=Double.valueOf(s2); switch( perator){//switch里面居然可以String jdk1.7后就可以咯! case "+": result=d1+d2; break; case "-": result=d1-d2; break; case "*": result=d1*d2; break; case "/": result=d1/d2; break; } return result; } }