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

来源:互联网 发布:淘宝小蜜投诉有用吗 编辑:程序博客网 时间:2024/05/01 01:53

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



0 0
原创粉丝点击