栈相关

两个栈实现队列:

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        int a;
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
               a=stack1.top();
               stack2.push(a);
               stack1.pop();
            }
        }
        a=stack2.top();
        stack2.pop();
        return a;
    }
}

 判断栈的压入弹出序列

public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA.length==0) return false;
        Stack<Integer> stack=new Stack<Integer>();
        for(int i=0,j=0;i<pushA.length;i++){
            stack.push(pushA[i]);
            while(j<popA.length&&stack.peek()==popA[j]){
                stack.pop();
                j++;
            }
            
        }
        return stack.isEmpty();
    }

 一个带加减乘除括号的表达式计算值

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Main m=new Main();
        String str="(56-20)/(4+2) ";//这里需要一个空格方便处理最后一位
        char[] res=m.trans(str.toCharArray());
        System.out.print(m.compute(res));
        
    }
    //把一个算数表达式转换为后缀表达式
    public char[] trans(char[] exp) {
        int i=0,j=0;
        char c=exp[i];
        i++;
        char[] postexp=new char[100];
        Stack<Character> stack=new Stack<>();
        while(i<exp.length) {
            switch (c) {
            case '(':
                stack.push('(');
                break;
            case ')':
                while(stack.peek()!='(') {
                    postexp[j]=stack.pop();
                    j++;
                }
                stack.pop();//把(也弹出去
                break;
            case '+':
            case '-':
                while(!stack.isEmpty()&&stack.peek()!='(') {
                    //要把其他符号弹出来(可能乘除,也可能和它同一个等级的)
                    postexp[j]=stack.pop();
                    j++;
                }
                stack.push(c);
                break;
            case '*':
            case '/':
                while(!stack.isEmpty()&&stack.peek()!='('&&(stack.peek()=='*'||stack.peek()=='/')) {
                    //同级的先弹出去
                    postexp[j]=stack.pop();
                    j++;                    
                }
                stack.push(c);
                break;
            case ' ':break;
            default:
                while(c>='0'&&c<='9') {
                    postexp[j]=c;j++;
                    c=exp[i];i++;
                }
                i--;//到不是数字的时候需要往前移动一位,因为最后的时候都会往后移动一位的
                postexp[j]='#';j++;
                break;
            }
            c=exp[i];i++;
        }
        while(!stack.isEmpty()) {
            postexp[j]=stack.pop();
            j++;
        }
        return postexp;
    }
    //根据后缀表达式计算值
    public double compute(char[] postexp) {
        Stack<Double> stack=new Stack<>();
        int i=0;
        char c=postexp[i];
        i++;
        //这个地方边界还有点问题,后面可以用链表
        while(i<13) {
            switch (c) {
            case '+':
                double after=stack.pop();
                double pre=stack.pop()+after;
                stack.push(pre);
                break;
            case '-':
                double afterb=stack.pop();
                double preb=stack.pop()-afterb;
                stack.push(preb);
                break;
            case '*':
                double afterc=stack.pop();
                double prec=stack.pop()*afterc;
                stack.push(prec);
                break;
            case '/'://这里可能有除0操作需要判断
                double afterd=stack.pop();
                double pred=stack.pop()/afterd;
                stack.push(pred);
                break;
            default:
                double d=0;
                while(c>='0'&&c<='9') {
                    d=10*d+c-'0';
                    c=postexp[i];
                    i++;
                }
                //这里不用回退是因为有一个#刚好跳过去
                stack.push(d);
                break;
            }
            c=postexp[i];i++;
        }
        return stack.peek();
    }
}

用栈来排序:

一个栈作为输入栈,一个作为输出栈,拿出输入栈栈顶元素,去和输出栈比较,找到第一个比他小的,上面的元素全部压入输入栈

//in是输入栈
     public Stack<Integer> sort(Stack<Integer> in){
         Stack<Integer> out=new Stack<>();
         if(in.isEmpty()) return out;
         int temp = in.peek();
         in.pop();
         if(in.isEmpty()) {
             out.push(temp);
             return out;
         }
         while(!in.isEmpty()||out.peek()>temp) {
             if(out.isEmpty()||out.peek()<=temp) {
                 out.push(temp);
                 temp=in.peek();
                 in.pop();
             }
             else
             {
                 in.push(out.peek());
                 out.pop();                 
             }
         }
         out.push(temp);
         return out;
     }

 找出来数组中每个元素后边第一个比它大的值A=[1,5,3,6,4,8,9,10] 输出[5, 6, 6, 8, 8, 9, 10, -1]

用栈来实现是需要O(n)的时间复杂度

public int[] findMax(int[] a) {
         Stack<Integer> stack=new Stack<>();
         int i=0;
         while(i<a.length) {
             if(!stack.isEmpty()&&a[i]>a[stack.peek()]) {
                 a[stack.pop()]=a[i];
             }
             else
             {
                 stack.push(i++);
             }
         }
         while(!stack.isEmpty()) {
             a[stack.pop()]=-1;
         }
         return a;
     }

 对于只有乘法和加法的算术表达式计算结果:

public static int normalCal(char[] a)
    {
       if(a.length==1)
           return a[0]-48;
       Stack<Integer> stack = new Stack<>();//数字栈
       Stack<Character> ctack = new Stack<>();//符号栈
       int i=0;
       while(i<a.length) {
           int temp=0;
           boolean flag=false;
           while(i<a.length&&a[i]>='0'&&a[i]<='9') {
               temp=temp*10+(a[i]-48);
               flag=true;
               i++;
           }
           if(flag) {//这一轮数字结束了,需要取出符号来计算了,当然只有乘号才弹出来
               stack.push(temp);
               if(!ctack.isEmpty()&&ctack.peek()=='*') {
                   int k=stack.peek();
                   ctack.pop();
                   stack.pop();
                   k*=stack.peek();
                   stack.pop();
                   stack.push(k);
               }
           }
           if(i<a.length&&(a[i]=='+'||a[i]=='*')) {
               ctack.push(a[i]);
               i++;
           }
       }
       int size=stack.size();
       int res=0;
       for(int j=1;j<=size;j++) {
           res+=stack.peek();
           stack.pop();
       }
       return res;      
    }

 括号嵌套,没遇到一个括号就反转字符串,当括号不匹配,直接返回-1

(ab(cd(ef(gh)))) 返回cdghfeba 

(ab(cd))(ef(gh)) 返回cdbaghfe

对于空括号的边界还是没有考虑

(ab(cd(ef(gh))))()()返回就会不对

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String str=sc.nextLine();
        Stack<Character> stack=new Stack<>();
        Stack<String> Sstack=new Stack<>();
        for(int i=0;i<str.length();i++) {
            StringBuilder sb=new StringBuilder();//放在外面防止出现()空括号的情况
            if(str.charAt(i)=='(') {
                stack.push('(');
                continue;
            }
            if(str.charAt(i)>='a'&&str.charAt(i)<='z') {                
                while(str.charAt(i)>='a'&&str.charAt(i)<='z') {
                    sb.append(str.charAt(i));
                    i++;
                }    
                i--;//上面那个会跳过去
                Sstack.push(sb.toString());//防止空括号
            }
            
            if(str.charAt(i)==')') {
                if(!stack.isEmpty()) {
                    stack.pop();//左括号出栈    
                    String aaa=Sstack.peek();            
                    StringBuilder temp=new StringBuilder(Sstack.peek());//字符串出栈
                    Sstack.pop();
                    String help="";
                    if(!Sstack.isEmpty()) {
                        help=Sstack.peek()+temp.reverse().toString();//再取栈顶的连接起来
                        Sstack.pop();
                    }
                    else
                       help=temp.reverse().toString();//再取栈顶的连接起来
                    Sstack.push(help);//新组成的再进栈
                }
                else
                {
                    System.out.println("括号不匹配不满足情况");
                    return;
                }
            }
        }
        if(!stack.isEmpty()) {
            System.out.println("括号不匹配不满足情况");
            return;
        }
        String res="";
        while(!Sstack.isEmpty()) {
            res=Sstack.pop()+res;    
        }
        System.out.println(res);
    }
}

 

posted @ 2019-07-18 10:05  LeeJuly  阅读(134)  评论(0)    收藏  举报