zoukankan      html  css  js  c++  java
  • 栈-----括号匹配+表达式计算

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



  • 相关阅读:
    python PyQt5
    传入一张图,生成它的油画版!(python实现)(转 )
    Python——画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)(转)
    Python3.7实现自动刷博客访问量(只需要输入用户id)(转)
    Python3 多线程的两种实现方式
    图片生成字符
    SqlServer性能优化 通过压缩与计算列提高性能(十一)
    json与bson的区别
    浅析Redis 和MongoDB
    Solr DocValues详解
  • 原文地址:https://www.cnblogs.com/oversea201405/p/3766908.html
Copyright © 2011-2022 走看看