跳到主要内容

14、数据结构与算法 - 实战:队列1

题目:如何使用两个栈实现队列
思路:假设用来实现队列的两个栈分别为stack1和stack2,保证两个栈总有一个为空
入队算法:
如果stack2不为空,先将stack2中的元素弹出并压入stack1;
将元素压入stack1
出队算法:
如果stack2不为空,那么栈顶元素就是队首元素,直接弹出栈顶元素即可;
如果stack2为空,那么先将stack1中的元素弹出并压入stack2,弹出stack2的栈顶元素;

/**
 * 使用两个栈实现队列
 * @param <AnyType> 元素类型
 */
public class QueueWithTwoStacks<AnyType> {
   
     

    LinkedListStack<AnyType> stack1;
    LinkedListStack<AnyType> stack2;

    /**
     * 构造方法
     */
    public QueueWithTwoStacks() {
        stack1 = new LinkedListStack<AnyType>();
        stack2 = new LinkedListStack<AnyType>();
    }

    /**
     * 判断是否为空
     * @return true 为空 false 不为空
     */
    public boolean isEmpty() {
        if (stack1.isEmpty() && stack2.isEmpty()) {
            return true;
        }
        return false;
    }

    /**
     * 入队
     * @param data 入队元素值
     */
    public void enQueue(AnyType data) {
        // 如果stack2中有值,先将值弹出压入stack1
        while (!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        // 将元素值压入stack1
        stack1.push(data);
    }

    /**
     * 出队
     * @return 出队元素
     */
    public AnyType deQueue() {
        // 如果stack2不为空,说明元素都在stack2中,此时stack2的栈顶元素就是队首元素
        if (!stack2.isEmpty()) {
            return stack2.pop();
        } else {
            // 如果stack2为空,说明元素都在stack1中,所以先将元素从stack1弹出,并压入stack2中
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
            // 此时stack2的栈顶元素就是队首元素
            return stack2.pop();
        }
    }
}

测试代码,如下:

/**
 * 使用两个栈实现队列测试方法
 */
public static void queueWithTwoStacksTest() {
    QueueWithTwoStacks<Integer> queue = new QueueWithTwoStacks<Integer>();

    // 结果为true
    System.out.println(queue.isEmpty());

    queue.enQueue(9);
    queue.enQueue(8);
    queue.enQueue(7);
    queue.deQueue();
    queue.enQueue(6);
    queue.enQueue(5);

    // 结果为false
    System.out.println(queue.isEmpty());

    // 结果为 8 7 6 5 
    while (!queue.isEmpty()) {
        System.out.print(queue.deQueue() + " ");
    }
}
 题目:如何使用两个队列来实现一个栈
 思路:假设用来实现栈的两个队列分别为queue1和queue2,确保总有一个队列是空的
 入栈算法:
 如果queue1为空,则对queue2执行入队操作
 否则就对queue1执行如对操作
 出栈算法:
 从有元素的队列移动n-1个元素到另一个队列,删除当前队列的最后一个元素,即可完成出栈
 如果queue1非空,那么从queue1移动n-1个元素到queue2中,然后对queue1的最后一个元素执行出队操作;
 如果queue2非空,那么从queue2移动n-1个元素到queue1中,然后对queue2的最后一个元素执行出队操作;

/**
 * 使用两个队列来实现一个栈
 * @param <AnyType>
 */
public class StackWithTwoQueues<AnyType> {
   
     

    LinkListQueue<AnyType> queue1;
    LinkListQueue<AnyType> queue2;

    /**
     * 构造方法
     */
    public StackWithTwoQueues() {
        queue1 = new LinkListQueue<AnyType>();
        queue2 = new LinkListQueue<AnyType>();
    }

    /**
     * 判断栈是否为空
     * @return true 是空栈 false 不是空栈
     */
    public boolean isEmpty() {
        return (queue1.isEmpty() && queue2.isEmpty());
    }

    /**
     * 入栈
     * 向非空的队列添加数据
     * @param data 入栈元素
     */
    public void push(AnyType data) {
        if (queue1.isEmpty()) {
            queue2.enQueue(data);
        } else {
            queue1.enQueue(data);
        }
    }

    /**
     * 出栈
     * @return 出栈元素
     */
    public AnyType pop() {
        int size;
        int count;
        if (queue1.isEmpty()) {
            count = 0;
            size = queue2.getQueueSize();
            while (count < size - 1) {
                queue1.enQueue(queue2.deQueue());
                count++;
            }
            return queue2.deQueue();
        } else {
            count = 0;
            size = queue1.getQueueSize();
            while (count < size - 1) {
                queue2.enQueue(queue1.deQueue());
                count++;
            }
            return queue1.deQueue();
        }
    }
}

测试代码,如下:

/**
 * 使用两个队列来实现一个栈的测试类
 */
public static void stackWithTwoQueuesTest() {
    StackWithTwoQueues<Integer> stack = new StackWithTwoQueues<Integer>();

    stack.push(1);
    stack.push(2);
    stack.push(3);
    stack.push(4);
    stack.push(5);

    // 结果为 5 4 3 2 1 
    while (!stack.isEmpty()) {
        System.out.print(stack.pop() + " ");
    }
}