【算法初探】前端学算法之用栈实现队列

330 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 6 天,点击查看活动详情

前因

上一篇文章中我们讲到了是一种先入后出的数据结构,并且也说了既然有先入后出的结构,肯定也有先入先出的数据结构,这一节我们就继续一起来学习一道关于对列的算法题 - 用栈实现队列,原题的地址在这里,题目的描述如下图所示:

image.png

js\ts中我们也是用数组(array)来模拟队列,前面也说了队列是先入先出的数据结构,因此队列的相关API跟栈差不多,也是pushshiftlength,下面我们就一起来简单实现一下队列吧!

队列

在前面我们已经说过队列是一种先进先出的数据结构,和一样,它本身也是不局限于任何语言的,下面我们一起来看一下用数组模拟队列的基本操作。

// 定于一个队列
const queue = [];
// 入队
queue.push(1);
queue.push(2);
queue.push(3);
const cur = queue.shift() // 出队

在前面旋转数组中我们讲到过,数组本身的shift操作是很慢的,但是这里我们先不用其它的数据结构来模拟队列,还是先用数组来实现,后续等学习新的数据结构链表时,再来看这个地方的问题。

下面我们一起来看一下这道题目的实现思路。

思路

我们这里是使用来实现队列,而的本质是先入后出队列却是先入先出,那么我们该如何将的执行效果转换成队列呢?这里我们定义一个(stack1),入栈的时候是将数据通过push都压入栈底,例如第一次入栈是A,第二次是B,第三次是C,那么stack1里面的值就是[C, B, A],然后我们要可以通过出栈将stack1里面的输入再入栈到stack2里面,这时候stack2里面的数据就变成了[A, B, C],最后当我们需要出队的时候,stack2里面的A就从栈顶拿出来了,这样就实现了队列的先进先出原则。

一起来看一下具体的代码实现吧。

代码实现

/*
 * 两个栈实现一个队列
 */
class MyQueue {
    // 私有变量,数组模拟栈
    private stack1: number[] = [];
    private stack2: number[] = [];
    // 队列的入队方法(添加方法)
    add(num: number) {
        this.stack1.push(num);
    }
    // 队列的出队方法(删除方法)
    delete(): number | null {
        // 定义一个临时变量
        let res;
        
        const stack1 = this.stack1;
        const stack2 = this.stack2;
        
        // 将 stack1 中所有元素都移动到 stack2 中
        while (stack1.length) {
            const cur = stack1.pop();
            if (cur != null) {
                stack2.push(cur);
            }
        }
        
        // 拿到 stack2 中最底部的值(出队)
        res = stack2.pop();
        
        // 将 stack2 中所有的元素再返还给 stack1
        while (stack2.length) {
            const cur = stack2.pop();
            if (cur != null) {
                stack1.push(cur);
            }
        }
        
        return res || null;
    }
    // 获取队列的长度
    get length(): number {
        return this.stack1.length;
    }
}

上面我们完成了这个算法的基本实现,我们也可以在TypeScript官网的Playground中测试一下该方法是否能够正常运行,运行的结果如下图所示:

image.png

具体的执行效果可以狠戳这里

上面我们已经实现了这个算法,那么我们按照惯例继续对我们实现的算法来做一个性能的分析。

性能分析

在这个算法的实现中,add时间的复杂度是O(1)delete的时间复杂度是O(n);整体的空间复杂度是O(n)。因为两个中存储的数据其实是一样的,因此这里还是O(n)

最后

我们总结一下这一节的大致内容。

队列先进先出的数据结构,是非常重要的一种数据结构,在日常的算法中会经常用到队列这种数据结构,而跟队列的效果是相反的,因此我们如果要用两个来模拟队列,就需要先搞清楚它们之间的区别,这样再来实现这道算法题时相对就比较简单明了一些。

最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

往期回顾

【算法初探】前端学算法之旋转数组(1)

【算法初探】前端学算法之旋转数组(2)

【算法初探】前端学算法之有效的括号