队列|图解Javascript数据结构

215 阅读3分钟

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

栈的概念

队列是一种先入先出(First In First Out)的数据结构。

什么是先入先出?相信大家都有在外面吃饭时碰到排队等号的情况吧,假设大家食量一样,干饭速度相同的情况下,是不是我比你先吃,我就先抹抹嘴走人了?队列就是这样的数据结构,先排上号的先吃先走,后排上号的晚吃晚走,依次有序

我们看个图加深一下理解:

队列.gif

可以发现,原本的进入顺序是 1->2->3,出去的顺序依然是 1->2->3依次有序

队列的几个名词

队头(front)与队尾(rear)

由于队列是 先入先出 的数据结构,所以队头就是最前面的元素,也就是第一个元素,队尾就是最新进入的元素,也就是最后一个元素。 捕获.PNG

入队(enQueue)与出队(deQueue)

我们都知道栈是 前入先出 的,入代表着进入,因此入队这个操作我们是向队尾添加元素,使之成为新的队尾元素,队尾元素是最后一个出去的。而出队代表着出,前入先出,所以出队这个操作是 将队头元素弹出。通过入队和出队这两个概念的理解,我们可以发现队列和栈的不同点在于,队列的头是第一个元素,出队出的是 队头 元素,也就是第一个元素,队列的尾是最后一个元素,入队是向 队尾 入的,也就是往最后面的位置添加,像 排队 一样。

捕获1.PNG

需要注意的是,我们每执行一次 出队 操作,就意味着这个被出队的位置 再也不能 存储数据了。如上图,一个 capacity=5 的队列,当前元素为 queue=[1,2,3],执行一次出队操作后,队头元素 1 出队了,剩余元素 [,2,3],此时队头已经变成 2 所在的位置了,那么 1 原本的位置上已经不能存储数据了。

这也是队列的弊端之一,后面会讲解一个新的数据结构——循环队列,就是用来解决容量浪费的问题。

分析队列结构

通过以上的几点相信大家对队列有了一定的理解,那么我们都知道 Javascript 中原生是没有提供队列这个数据结构的,所以如果我们想要使用,则需要手动去实现它。那么基于前面理解的几个特性,我们很容易就联想到 使用数组来模拟队列结构

手撕队列

class Queue {
    constructor(capacity) {
        this.queue = [];
        this.start = 0;
        this.end = 0;
        this.capacity = capacity;
    }
    isEmpty() {
        return this.start === this.end;
    }
    front() {
        return this.queue[this.start];
    }
    rear() {
        if (this.isEmpty()) return -1;
        return this.queue[this.end - 1];
    }
    enQueue(v) {
        if (this.end >= this.capacity) return false;
        this.queue[this.end++] = v;
        return true;
    }
    deQueue() {
        if (this.isEmpty()) return -1;
        return this.queue[this.start++];
    }
}

const queue = new Queue(3);
console.log(queue.isEmpty()); // true
console.log(queue.deQueue()); // -1
console.log(queue.enQueue(1)); // true
console.log(queue.enQueue(2)); // true
console.log(queue.rear()); // 2
console.log(queue.enQueue(3)); // true
console.log(queue.rear()); // 3
console.log(queue.enQueue(4)); // false
console.log(queue.deQueue()); // 1
console.log(queue.enQueue(5)); // false

巩固练习题

大家有需要巩固练习的也可以看看几道 LeetCode 上的题目: