数据结构(JS实现)——队列与优先级队列

89 阅读2分钟

一.什么是队列

只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表;进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列);队列具有先进先出(FIFO)的特性。

二.队列的封装

我们封装队列常见方式有两种:

基于数组实现

基于链表实现

我们使用数组实现

  function Queue() {
    // 属性
    this.items = [];
    
    // 方法
    // enqueue(element): 向队列尾部添加一个新的项
    // dequeue(): 移除队列的第一项,并返回被移除的元素
    // front(): 返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动
    // isEmpty(): 判空
    // size(): 返回长度
    // tostring(): 输出

}

三、队列的常见的操作

enqueue(element):向队列尾部添加一个新的项

dequeue():移除队列的第一项,并返回被移除的元素

front():返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动

isEmpty():判空

size():返回长度

tostring():输出

3.1 enqueue(element):向队列尾部添加一个新的项

 Queue.prototype.enqueue = function (element) {
        this.items.push(element);
        return element;
    } 

3.2 dequeue():移除队列的第一项,并返回被移除的

 Queue.prototype.dequeue = function () {
        return this.items.shift();
    }

3.3 front():返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动

  Queue.prototype.front = function () {
        return this.items[0];
    }

3.4 isEmpty():判空

  Queue.prototype.isEmpty = function () {
        return this.items.length == 0;
    }

3.5 size():返回长度

  Queue.prototype.size = function () {
        return this.items.length;
    }

3.6 tostring():输出

  Queue.prototype.tostring = function () {
        var str='';
        for (let index = 0; index < this.items.length; index++) {
            str+=this.items[index]+' ';            
        }
        return str;
    }

四. 面试题:击鼓传花

/* 击鼓传花游戏,玩家按顺序从1开始数数,数到指定的num时出局 剩下的玩家接着重新从1开始数数 最后剩下的玩家获胜 */

 function passGame(nameList,num) {
        // 创建一个队列结构
        var list=new Queue();
        // 将所有人加入队列中
        for (let index = 0; index < nameList.length; index++) {
            list.enqueue(nameList[index])
        }
        
        while (list.size()!=1) {
            // 每次循环遍历nun,每遍历一个人将其从对头移至对位
            for (let i = 0; i <  num-1; i++) {
                list.enqueue(list.dequeue());
            }
            // 循环结束后将对头元素(即目标值)删除
            list.dequeue();
        }
        console.log(list.size());
        // 循环结束只剩下一个人就是target
        return list.front();
    }
    var names=["Lily","lucy","tom","Lilei","why"];
    
    console.log(passGame(names,3));

五. 优先级队列的封装

5.1概念

如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列 这种数据结构。

5.2 封装

其实关于优先级队列的封装,大致思路和普通队列时相似的,只有添加方法需要考虑优先级的情况。

 function PriorityQueue() {
        // 属性封装
        var items=[];

        // 队列元素
        function QueueElement(element,priority) {
            this.element=element;
            this.priority=priority;
        }
        
        // 添加方法
        。。。
    }

5.3 添加方法

     PriorityQueue.prototype.enqueue = function (element, priority) {
            // 创建QueueElement对象
            var newQueueElement = new QueueElement(element, priority);
         //判断队列长度是否为空
            if (this.items.length == 0) {
                this.items.push(newQueueElement);
            } else {
                //不为空时我们遍历比较优先级插入即可
                //设置标记(如果比较完发现不符合条件,则说明不需要交换位置,则插入在队尾即可)
                var flag = false;
                
                for (let i = 0; i < this.items.length; i++) {
                    if (newQueueElement.priority < this.items[i].priority) {
                        this.items.splice(i, 0, newQueueElement);
                        flag = true
                        break;
                    }
                }
                if (!flag) {
                    this.items.push(newQueueElement);
                }
            }
        }

六.源码

队列:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script src="Queue.js"></script>
<script>
    function Queue() {
    // 属性
    this.items = [];
    // 方法
    // enqueue(): 向队列尾部添加一个新的项
    Queue.prototype.enqueue = function (element) {
        this.items.push(element);
        return element;
    } 
    // dequeue(): 移除队列的第一项,并返回被移除的元素
    Queue.prototype.dequeue = function () {
        return this.items.shift();
    }
    // front(): 返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动
    Queue.prototype.front = function () {
        return this.items[0];
    }
    // isEmpty(): 判空
    Queue.prototype.isEmpty = function () {
        return this.items.length == 0;
    }
    // size(): 返回长度
    Queue.prototype.size = function () {
        return this.items.length;
    }
    // tostring(): 输出
    Queue.prototype.tostring = function () {
        var str='';
        for (let index = 0; index < this.items.length; index++) {
            str+=this.items[index]+' ';            
        }
        return str;
    }
}
    var queue=new Queue();
    queue.enqueue('aa');
    queue.enqueue('bb');
    queue.enqueue('cc');
    queue.enqueue('dd');
    console.log(queue.tostring());
    queue.dequeue();
    console.log(queue.tostring());
    queue.dequeue();
    console.log(queue.tostring());
    console.log(queue.isEmpty());
    console.log(queue.size());
</script>
</html>

优先级队列:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    function PriorityQueue() {
        // 属性封装
        this.items = [];

        // 队列元素
        function QueueElement(element, priority) {
            this.element = element;
            this.priority = priority;
        }

        // 添加方法
        PriorityQueue.prototype.enqueue = function (element, priority) {
            // 创建QueueElement对象
            var newQueueElement = new QueueElement(element, priority);
            if (this.items.length == 0) {
                this.items.push(newQueueElement);
            } else {
                var flag = false;
                for (let i = 0; i < this.items.length; i++) {
                    if (newQueueElement.priority < this.items[i].priority) {
                        this.items.splice(i, 0, newQueueElement);
                        flag = true
                        break;
                    }
                }
                if (!flag) {
                    this.items.push(newQueueElement);
                }
            }
        }
        // dequeue(): 移除队列的第一项,并返回被移除的元素
        PriorityQueue.prototype.dequeue = function () {
            return this.items.shift();
        }
        // front(): 返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动
        PriorityQueue.prototype.front = function () {
            return this.items[0];
        }
        // isEmpty(): 判空
        PriorityQueue.prototype.isEmpty = function () {
            return this.items.length == 0;
        }
        // size(): 返回长度
        PriorityQueue.prototype.size = function () {
            return this.items.length;
        }
        // tostring(): 输出
        PriorityQueue.prototype.tostring = function () {
            var str = '';
            for (let index = 0; index < this.items.length; index++) {
                str += this.items[index].priority+","+this.items[index].element+ ' ';
            }
            return str;
        }
    }


    var nn=new PriorityQueue();
    nn.enqueue('aa',111);
    nn.enqueue('bb',200);
    nn.enqueue('cc',50);
    nn.enqueue('dd',66);
    console.log(nn.tostring());
</script>

</html>