JavaScript数据结构之队列

140 阅读3分钟

什么是队列

  • 队列是一种操作受限的线性表。在这种线性表上,插入限定在表的一端进行,删除限定在表的另一端进行。允许插入的一端称为队尾,允许删除的一端称为队头。队列有两种存储方法:顺序存储和链式存储 顺序队列这种顺序存储结构容易产生假溢出。克服假溢出的方法通常有两种:
  • 将队列中的所有元素均向最前端的位置移动;
  • 采用循环队列(相对于顺序队列存储方式物理存储方式没有发生改变,认为想象将顺序队列的首位相连)。

一个队列的基本功能

1、enqueue 向队列尾部添加一个(或多个)新的项
2、dequeue 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
3、head 返回队列第一个元素,队列不做任何变动
4、tail 返回队列最后一个元素,队列不做任何变动
5、isEmpty 队列内无元素返回 true,否则返回 false
6、size 返回队列内元素个数
7、clear 清空队列

class Queue {
    constructor() {
        this.queueArray = [];
    }

    // 向队列尾部添加一个(或多个)新的项
    enqueue(value) {
        return this.queueArray.push(value)
    }

    // 清空队列
    clear() {
        return this.queueArray = []
    }

    // 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
    dequeue() {
        return this.queueArray.shift()
    }

    // 返回队列第一个元素,队列不做任何变动
    head() {
        return this.queueArray[0]
    }

    // 返回队列最后一个元素,队列不做任何变动
    tail() {
        return this.queueArray[this.queueArray.length - 1]
    }

    // 队列内无元素返回 true,否则返回 false
    isEmpty() {
        return !this.queueArray.length
    }

    // 返回队列内元素个数
    size() {
        return this.queueArray.length
    }
}

什么是优先级队列

元素的添加或者删除是基于优先级的。实现优先队列有两种方式:①优先添加,正常出列;②正常添加,优先出列

// 优先队列
class RankQueue {
    constructor() {
        this.rankQueueArray = []

        this.QueueItem = function (item, rank) {
            this.item = item;
            this.rank = rank
        }
    };

    // 向队列添加一个(或多个)新的项
    enqueue(item, rank) {
        let queueItem = new this.QueueItem(item, rank);

        if (this.isEmpty()) {
            // 队列为空,直接添加
            this.rankQueueArray.push(queueItem);
        } else {
            // 队列不为空,遍历,对比优先级
            let flag = false;
            for (let target = 0; target < this.rankQueueArray.length; target++) {
                // 判断优先级 
                if (this.rankQueueArray[target].rank < queueItem.rank) {

                    this.rankQueueArray.splice(target, 0, queueItem);
                    flag = true
                    break;

                }
            }

            // 优先级都大于插入的,直接添加至末尾
            if (!flag) this.rankQueueArray.push(queueItem)
        }
    }

    // 清空队列
    clear() {
        return this.rankQueueArray = []
    }

    // 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
    dequeue() {
        return this.rankQueueArray.shift()
    }

    // 返回队列第一个元素,队列不做任何变动
    head() {
        return this.rankQueueArray[0]
    }

    // 返回队列最后一个元素,队列不做任何变动
    tail() {
        return this.rankQueueArray[this.rankQueueArray.length - 1]
    }

    // 队列内无元素返回 true,否则返回 false
    isEmpty() {
        return !this.rankQueueArray.length
    }

    // 返回队列内元素个数
    size() {
        return this.rankQueueArray.length
    }
}

什么是循环队列

循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

class CircularQueue {
    constructor(capacity) {
        /**
         * @desc 容量
         */
        this.capacity = capacity;

        /**
         * @desc 队列头部
         */
        this.head = -1;

        /**
         * @desc 队列尾部
         */
        this.tail = -1;

        /**
         * @desc 数据
         */
        this.circularQueueArray = [];
    }

    // 向循环队列插入一个元素
    enqueue(value) {
        // 是否已满
        if (this.isFull()) {
            return undefined
        };
        // 是否为空
        if (this.isEmpty()) {
            this.head = 0
        };

        this.tail = (this.tail + 1) % this.capacity
        this.circularQueueArray[this.tail] = value;
    }

    // 清空循环队列
    clear() {
        this.head = -1;
        this.tail = -1;
    }

    // 从循环队列中删除首部元素
    dequeue() {
        if (this.isEmpty()) return undefined

        if (this.head === this.tail){
            this.head = this.tail = -1
        }else {
            this.head = (this.head + 1) % this.capacity
        }
    }

    // 返回队列第一个元素,队列不做任何变动
    head() {
        if (!this.isEmpty()) {
            return this.circularQueueArray[this.head]
        }
    }

    // 返回队列最后一个元素,队列不做任何变动
    tail() {
        if (!this.isEmpty()) {
            return this.circularQueueArray[this.tail]
        }
    }

    // 队列内无元素返回 true,否则返回 false
    isEmpty() {
        return !this.circularQueueArray.length
    }

    // 队列是否已满
    isFull() {
        return this.head == (this.tail + 1) % this.cap;
    }

}

有问题留言评论