简单的用栈实现队列

简单的用栈实现队列

队列是一种先进先出的数据结构,栈是一种先进后出的数据结构,形象一点就是这样:

在这里插入图片描述

在面试中常常会问到这样一个问题:怎么使用栈来实现一个队列?如何用队列来实现一个栈?

前者问的较多,后者问的较少,但掌握得多也不是坏事嘛,接下来我们就来解析下这两个问题。

用栈实现队列

首先,队列的 API 如下:

class MyQueue {

    /** 添加元素到队尾 */
    public void push(int x);

    /** 删除队头的元素并返回 */
    public int pop();

    /** 返回队头元素 */
    public int peek();

    /** 判断队列是否为空 */
    public boolean empty();
}

我们使用两个栈s1, s2就能实现一个队列的功能。

class MyQueue {
    private Stack<Integer> s1, s2;

    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }
    // ...
}

首先来解决入队的问题,当调用push让元素入队时,只要把元素压入s1即可:

在这里插入图片描述

/** 添加元素到队尾 */
public void push(int x) {
    s1.push(x);
}

那么使用peek查看队头的元素怎么办呢?按道理队头元素应该是 1,但是在s1中 1 被压在栈底,现在就要轮到s2起到一个中转的作用了:

s2为空时,可以把s1的所有元素取出再添加进s2,这时候s2中元素就是先进先出顺序了

在这里插入图片描述

/** 返回队头元素 */
public int peek() {
    if (s2.isEmpty())
        // 把 s1 元素压入 s2
        while (!s1.isEmpty())
            s2.push(s1.pop());
    return s2.peek();
}

同理,对于pop操作,只要操作s2就可以了。

/** 删除队头的元素并返回 */
public int pop() {
    // 先调用 peek 保证 s2 非空
    peek();
    return s2.pop();
}

最后,如何判断队列是否为空呢?如果两个栈都为空的话,就说明队列为空:

/** 判断队列是否为空 */
public boolean empty() {
    return s1.isEmpty() && s2.isEmpty();
}

至此,就用栈结构实现了一个队列,核心思想是利用两个栈互相配合。

用队列实现栈

首先看下栈的 API:

class MyStack {

    /** 添加元素到栈顶 */
    public void push(int x);

    /** 删除栈顶的元素并返回 */
    public int pop();

    /** 返回栈顶元素 */
    public int top();

    /** 判断栈是否为空 */
    public boolean empty();
}

有两种方法实现,分别是用两个队列和一个队列的方法。
总的来说,无论是双队列还是单队列实现,都是确保调用push()方法时,新增的元素在栈顶就行了。

先用两个队列来实现:

class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;
    public MyStack() {
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }

    /** 确保queue1的前端元素为栈顶元素 */
    public void push(int x) {
        // 首先将元素入队到queue2
        queue2.offer(x);
        // queue1的全部元素依次出队并入队到queue2
        // 此时queue2的前端的元素即为新入栈的元素
        while (!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        // 两队列互换
        Queue<Integer> temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }

    public int pop() {
        return queue1.poll();
    }

    public int top() {
        return queue1.peek();
    }

    public boolean empty() {
        return queue1.isEmpty();
    }
}

单队列实现:

class MyStack {
    Queue<Integer> queue;
    public MyStack() {
        queue = new LinkedList<Integer>();
    }

    /**  确保队列的前端元素为栈顶元素 */
    public void push(int x) {
        // 获得入栈前元素个数
        int n = queue.size();
        queue.offer(x);
        // 将队列中的前n个元素依次出队并入队到队列
        // 此时队列的前端的元素即为新入栈的元素
        for (int i = 0; i < n; i++) {
            queue.offer(queue.poll());
        }
    }

    public int pop() {
        return queue.poll();
    }

    public int top() {
        return queue.peek();
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值