《剑指offer》面试题9:用两个栈实现队列

###题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail 和deleteHead ,分别完成在队列尾部插入节点和在队列头部删除节点的功能。(java版:用两个栈,实现队列的从队尾插入元素offer()和从队头抛出元素poll()。)

思路:

(1)对于插入操作,栈与队列都是从队尾进行,因此一行代码就可以完成offer()
(2)对于弹出操作,队列先进先出从队头开始,而栈后进先出从队尾开始,要想取到队头元素,就得需要第二个栈stack2的协助:弹出时将stack1的元素依次取出放到stack2中,此时stack2进行弹出的顺序就是整个队列的弹出顺序。而如果需要插入,放到stack1中即可。
总结下,stack1负责插入,stack2负责弹出,如果stack2为空了,将stack1的元素依次弹出并存放到stack2中,之后对stack2进行弹出操作。

基于以上分析,java参考代码如下:

package chapter2;

import java.util.ArrayDeque;

public class P68_TwoStacksQueue {
    private ArrayDeque<Integer> stack1=new ArrayDeque<>();//pushStack
    private ArrayDeque<Integer> stack2=new ArrayDeque<>();//popStack

    public void push(int val){
        stack1.addFirst(val);
    }

    public int pop(){
        if(stack1.isEmpty()&&stack2.isEmpty()){
            throw new RuntimeException("Queue is empty!");
        }else if(stack2.isEmpty()){
            while (!stack1.isEmpty()){
                stack2.addFirst(stack1.pollFirst());//stack1--->stack2 all.
            }
        }
        return stack2.pollFirst();
    }

    public int peek(){
        if(stack1.isEmpty()&&stack2.isEmpty()){
            throw new RuntimeException("Queue is empty!");
        }else if(stack2.isEmpty()){
            while (!stack1.isEmpty()){
                stack2.addFirst(stack1.pollFirst());//stack1--->stack2 all.
            }
        }
        return stack2.peekFirst();
    }

    public static void main(String[] args) {
        P68_TwoStacksQueue myque=new P68_TwoStacksQueue();
        myque.push(1);
        myque.push(2);
        System.out.println(myque.pop());
        System.out.println(myque.pop());
        myque.push(3);
        myque.push(4);
        System.out.println(myque.peek());
        System.out.println(myque.pop());
        System.out.println(myque.pop());
        //System.out.println(myque.pop());//Exception

    }

}

C++分析如下:

template <typename T> class CQueue
{
public:
	CQueue(void);
	~CQueue(void);

	void appendTail(const T& node);
	T deleteHead();
private:
	stack<T> stack1;
	stack<T> stack2;
};

分析:当stack2 不为空时,在stack2 中的栈顶元素是最先进进入队列的元素,可以弹出。当stack2 为空时,我们把stack1 中的元素逐个弹出并压入stack2。由于先进入队列的元素被压到stack1 的底端,经过弹出和压入操作之后就处于stack2 的顶端,又可以直接弹出。

C++参考代码如下:

template<typename T> void CQueue<T>::appendTail(const T& element)
{
	stack1.push(element);
}
template<typename T> void CQueue<T>::deleteHead()
{
	if(stack2.size()<=0)
	{
		while(stack1.size()>0)
		{
			T& data=stack1.top();
			stack1.pop();
			stack2.push(data);
		}
	}

	if(stack2.size()==0)
		throw new exception("queue is empty");

	T head==stack2.top();
	stack2.pop();

	return head;
}
用两个队列实现一个栈

java参考代码如下:

package chapter2;

import chapter4.P151_MirrorOfBinaryTree;

import java.util.ArrayDeque;

public class P68_TwoQueuesStack {
    private ArrayDeque<Integer> queue=new ArrayDeque<>();
    private ArrayDeque<Integer> help=new ArrayDeque<>();

    public void push(int val){
        queue.addLast(val);
    }

    public int pop(){
        if(queue.isEmpty()){
            throw new RuntimeException("Stack is empty!");
        }
        while (queue.size()>1){
            help.addLast(queue.pollFirst());//queue-->help
        }
        int res=queue.pollFirst();
        swap();
        return res;
    }

    public int peek(){
        if(queue.isEmpty()){
            throw new RuntimeException("Stack is empty!");
        }
        while (queue.size()>1){
            help.addLast(queue.pollFirst());//queue-->help
        }
        int res=queue.pollFirst();
        help.addLast(res);
        swap();
        return res;
    }

    public void swap(){//call by value !!
        ArrayDeque<Integer> temp;
        temp=queue;
        queue=help;
        help=temp;
    }

    public static void main(String[] args) {
        P68_TwoQueuesStack stack= new P68_TwoQueuesStack();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }
}

测试用例:

a.往空的队列里添加、删除元素。
b.往非空的队列里添加、删除元素。
c.连续删除元素直至队列为空。

参考:

https://www.jianshu.com/p/e92f42b892d0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值