栈-----括号匹配+表达式计算

第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;
	   }
}	 
 



posted @ 2014-03-19 23:14  IT专业户  阅读(243)  评论(0编辑  收藏  举报