栈和队列相关编程——验证栈序列、两个栈模拟一个队列、两个队列模拟一个栈

目录

栈和队列基本理解

1.验证栈序列(出栈序列判断)——leetcode

2.两个队列模拟一个栈

3.两个栈模拟一个队列

3段代码的测试结果


栈和队列基本理解

1. 栈:是一个先进后出的线性表,只在栈顶(表尾)进行增加和删除的操作,栈底 为表头。一般有顺序栈链栈

        1.1.顺序栈和链式栈在进行插入删除操作的时间复杂度

        顺序栈:头插:O(N),头删O(N);尾插:O(1),尾删O(1)

        链式栈:头插:O(1),头删O(1);尾插:O(1),尾删O(N)

2. 队列:特征是先进先出,在表的一头进行插入操作,在另一头进行删除操作,可以用链表的形式来实现。

        顺序队列:头插:O(N) , 尾删:O(1);尾插:O(1),头删 O(N)

 1.验证栈序列(出栈序列判断)——leetcode

题目:

给定 pushed 和 popped 两个序列,每个序列中的值都不重复,当他们的入栈序列已知,判断给定的出栈序列是否正确。
输入:入栈: [1,2,3,4,5],出栈:[3,5,4,2,1]
输出:true
入1,2,3,出3,入4,5,出5,4,2,1

思路:

  • 当   入栈序列为空   或   出栈序列为空   或   出栈序列和入栈序列的长度不相等   时,返回false。
  • 定义两个数组,inOrder[] 为入栈序列的数组,outOrder[] 为出栈序列的数组;
  • 定义两个指针i,j,i 指向入栈序列,j 指向出栈序列;
  • 定义一个栈,当stack.isEmpty() || stack.peek() != outOrder[j](即栈为空或栈顶元素不等于当下待比较的出栈序列数组下标为j的元素,则 i++;继续入栈,栈顶元素改变;若相同,则栈顶元素pop操作,变为下一个,i不变,j++;即j的下一个元素进行比较。
  • 最后,若i== j (即全部遍历完)并且 stack.isEmpty() 为真,则说明出栈序列正确;

代码1: 

    public static boolean validateStackSequences(int[] inOrder, int[] outOrder) {
        if (inOrder == null || outOrder == null || inOrder.length != outOrder.length) {
            return false;
        }
        int i = 0;// i 遍历inOrder序列
        int j = 0;// j遍历outOrder 序列
        Stack<Integer> stack = new Stack<>();

        if (inOrder.length == 0 && outOrder.length == 0) {
            return true;
        }
        // 避免数组越界 如果长度为0,则下一步push(0) 出错
        stack.push(inOrder[i++]);// 栈入第一个元素

        // 当最后一个inOrder 的元素遍历后,i还自增了一下,
        // 所以在下一个while循环中,i不符合,会提前退出
        // i一定先比j遍历完,所以为了不让循环提前退出,则i<= inOrder.length;
        while (j < outOrder.length && i <= inOrder.length) {
            //避免栈里的元素全部出栈,空指针报错
            if (stack.isEmpty() || stack.peek() != outOrder[j]) {

                // 出现错误:当出栈序列出现错误时,将会满足以上if语句的条件,则会执行if中的语句
                // 当栈顶元素和出栈序列中下标为j的元素不相等的时候,栈中会一直入元素,当入到下标为inOrder.length的时候,就会出现数组越界异常
                if (i < inOrder.length) {
                    stack.push(inOrder[i]);
                    // 如果栈为空,或者入栈的当前元素和出栈的当前元素不相同,则i++;
                }
                i++; // i++不能放在以上if语句中,否则当以上if语句进不去的时候,i不能自增(即当i遍历完);while循环不能退出。
            }
            if (stack.peek() == outOrder[j]) {
                stack.pop();
                j++;
                // 如果相同,则j++;所有元素都出去了,所以j = 5(假设为5个元素),
                // 从0开始,当stack.peek() == outOrder[0]时,j再自增,j=1,
                // 当最后一个元素outOrder[4]后,j=5,退出循环
            }
        }
        if (i == j && stack.isEmpty()) {
            return true;
        } else {
            return false;
        }
    }

代码2:

public boolean InOutOfStack(int[] pushed, int[] popped) {
        if(pushed.length == popped.length){
            Stack<Integer> stack = new Stack<>();
            int i = 0;
            int j = 0;
            while(i<pushed.length && j<popped.length){ 
                while(i<pushed.length && (stack.empty()||stack.peek()!=popped[j])){
                    stack.push(pushed[i]);
                    i++;
                }
                while(j<popped.length&&!stack.empty()&&stack.peek() == popped[j]){
                    stack.pop();
                    j++;
                }
            }
            return stack.empty();
        }
        return false;

    }

 

2.两个队列模拟一个栈

思路:

  • 定义两个队列,让序列先入queue1,在出队列,剩下一个元素,将其他元素再入queue2,将剩下的元素poll()出来。
  • queue2 中的操作同上

代码1: 

    public static void twoQueueToOneStack(int[] arr) {
        Queue<Integer> queue1;
        Queue<Integer> queue2;
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
        for (int i = 0; i < arr.length; i++) {
            queue1.offer(arr[i]);// 将元素入到一个队列中
        }
        int total = arr.length;// 元素总大小
        int count;
        while (total > 0) {  // 不能将条件置为total != 0;total可能为负数,所以设为>0,为保险
            count = total;
            while (count > 1) { // 当元素的个数大于一时,队列2入队列1中的元素
                queue2.offer(queue1.peek());
                queue1.poll();// 更新queue1,每次queue2 获取一个值后,queue1 相应的删除一个值
                count--;
            }
            if(!queue1.isEmpty()) { // 必须判断该队列是否为空,若为空,则打印出来的值为null
                System.out.print(queue1.peek()+" ");
                total--;// 总数-1;
                queue1.poll();// queue 更新,置为null
            }
            count = total;
            while (count > 1) {
                queue1.offer(queue2.peek());
                queue2.poll();
                count--;
            }
            if(!queue2.isEmpty()) {
                System.out.print(queue2.peek()+" ");
                queue2.poll();
                total--;
            }
        }
        System.out.println("");
    }

代码2:

Queue<Integer> queue1;
    Queue<Integer> queue2;

    public pratice() { // 需要一个一个的输入value,并一个一个的打印栈内的元素
        // 队列是一个典型的先进先出的容器,Java中LinkedList提供了方法以支持队列的行为,并且它实现了Queue接口,
        // 因此LinkedList可以用作Queue的一种实现。
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }
    public void push(int value){  //
        queue1.offer(value);
    }
    public Integer pop(){
        if(queue1.size() == 1){
            return queue1.poll();
            // poll:将首个元素从队列中弹出,如果队列是空的,就返回null
            //peek:查看首个元素,不会移除首个元素,如果队列是空的就返回null
            //element:查看首个元素,不会移除首个元素,如果队列是空的就抛出异常
        }else{
            while(queue1.size() > 1){
                queue2.offer(queue1.poll());
            }
            int res = queue1.poll();   // 最后一个元素
            while(!queue2.isEmpty()){
                queue1.offer(queue2.poll());
            }
            return res;
        }
    }
    public int top(){
        if(queue1.size() == 1 ){
            return queue1.peek();
        }else{
            while(queue1.size() > 1){
                queue2.offer(queue1.poll());
            }
            int res =  queue1.poll();
            while (!queue2.isEmpty()){
                queue1.offer(queue2.poll());
            }
            queue1.offer(res);
            return res;
        }
    }
    public boolean isEmpty(){
        return queue1.isEmpty();
    }

3.两个栈模拟一个队列

思路:

  • 先准备一个栈,让序列先入栈,如先入 1  2  3  4  5 ,再让这个序列出原来的栈,为5  4  3  2  1.进入辅助的栈,入栈序列是 5 4 3 2 1,在进行出栈时就变成了1 2 3 4 5
  • 即实现了队列的特征:先进先出

代码1: 

twoStackToOneQueue(int[] arr){
        if(arr == null || arr.length == 1){
            return;
        }
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        // 将arr数据依次入栈1
        for(int i = 0;i<arr.length;i++){
            stack1.push(arr[i]);
        }
        // 将栈1数据依次入栈2
        while(!stack1.isEmpty()){
            stack2.push(stack1.peek());
            stack1.pop();
        }
        //将栈2数据依次打印出来
        while(!stack2.isEmpty()){
            System.out.println(stack2.pop());
        }
    }
 public static void main(String[] args) {
        int[] brr = {1,2,3,4,5};
        twoStackToOneQueue(brr);
    }
}

代码2:

 Stack<Integer> stack1 = new Stack<>();
    Stack<Integer> stack2 = new Stack<>();

    public void enQueue(int value){
        stack1.push(value);
    }
    public int outQueue(){
        if(stack2.isEmpty()){  
            while(!stack1.isEmpty()){
                stack1.pop();// 栈1 元素先pop出来;
                stack2.push(stack1.pop()); // 进入栈2
            }
        }
        return stack2.pop();
    }

3段代码的测试结果

测试代码:

public static void main(String[] args) {
        int[] brr = {1,2,3,4,5}; // 测试三个题中的代码1
        int[] arr = {4,3,2,1,5};
        System.out.println(validateStackSequences(brr,arr));// 验证栈序列  true
        twoStackToOneQueue(brr); // 两个栈模拟一个队列
        twoQueueToOneStack(brr); // 两个队列模拟一个栈
        pratice queue1 = new pratice();
        queue1.push(1); //代码2:两个队列模拟一个栈
        queue1.push(2);
        queue1.push(3);
        queue1.push(4);
        System.out.print(queue1.pop() + " ");
        System.out.print(queue1.pop()+" ");
        System.out.print(queue1.pop()+" ");
        System.out.println(queue1.pop()+" ");
        pratice stack = new pratice();
        stack.push(1);// 代码2: 两个栈模拟一个队列
        stack.push(2);
        System.out.print(stack.pop()+" ");
        System.out.println(stack.pop()+" ");
        System.out.println(InOutOfStack(brr,arr)); // true
    }
}

得到结果为:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值