JavaScript数据结构与算法 -- 队列/优先级队列

1.队列结构

队列(Queue)结构是一种受限的线性表,先进先出(FIFO First In First Out)

  • 受限之处在于,它只允许在表的前端(front)进行删除操作
  • 在表的后端(rear)进行插入操作
    在这里插入图片描述

2.生活中类似的队列结构

  • 电影院,商场排队,游乐场排队买票
  • 打印机打印文件

3.队列的应用

打印队列:

  • 有五份文档需要打印,这些文档会按照次序放入到打印队列中
  • 打印机会一次从队列中取出文档,优先放入的文档,优先被取出,并且对该文档进行打印
  • 依此类推,知道文档中不再有新的文档

线程队列:

  • 在开发中,为了让人物并行处理,通常会开启多个线程
  • 但是我们不能让大量的线程同时运行处理任务(占用过多的资源)
  • 这个时候,如果需要开启线程处理任务的情况,我们就会使用线程队列
  • 线程队列会按照次序来启动线程

4.队列的常见操作

  • enqueue(element):向队列尾部添加一个(或多个)新的元素
  • dequeue():移除队列的第一个元素,最前面的项,并返回被移除的元素
  • front():返回队列中的第一个元素,队列不做任何变动。
  • isEmpty():如果队列中不包含任何元素,返回true,否则返回false
  • size():返回队列包含的元素个数,与数组的length属性类似
  • toString():将队列中的元素内容,转成字符串形式

5.队列类的创建

队列的实现和栈一样,有两种方案

  • 基于数组实现
  • 基于链表实现
//封装队列类
    function Queue(){
        //属性
        this.items = [];

        //方法
        //1.将元素加入到队列中
        Queue.prototype.enqueue = function(element){
            this.items.push(element);
        }
        //2.从队列中删除前端元素
        Queue.prototype.dequeue = function(){
            this.items.shift()
        }
        //3.查看前端的元素
        Queue.prototype.front = function(){
            return this.items[0];
        }
        //4.查看队列是否为空
        Queue.prototype.isEmpty = function(){
            return this.items.length == 0;
        }
        //5.查看队列中元素的个数
        Queue.prototype.size = function(){
            return this.items.length;
        }
        //6.toString方法
        Queue.prototype.toString = function(){
            let resultString = '';
            for(let i = 0; i < this.items.length; i++){
                resultString += this.items[i] + ',';
            }
            return resultString;
        }
    }

    // 使用队列
    let queue = new Queue();
    //从后端添加元素
    queue.enqueue(1);
    queue.enqueue(2);
    queue.enqueue(3);
    queue.enqueue(4);
    queue.enqueue(5);
    console.log(queue);
    //从前端删除元素
    queue.dequeue();
    queue.dequeue();
    console.log(queue);
    //查看前端的元素
    console.log(queue.front());
    //查看队列是否为空
    console.log(queue.isEmpty());
    //查看队列元素的个数
    console.log(queue.size());
    //队列的toString方法
    console.log(queue.toString());

6.队列提醒讲解–击鼓传花

  • 击鼓传花: 一人敲鼓,剩下的人围成一圈,开始传花,当鼓声停了,花在谁手上,谁表演节目,完了继续执行

  • 新规则: 一群人围成一圈数数,数到某个数字的人被淘汰,最终留下的人胜利,算出来最后剩下的人是原来在那个位置上的人

  • 参数:所有参与者的姓名,基于的数字

  • 结果:最终剩下的一个人的姓名

  • 代码实现的思想:(加入数字为5)
    依次将学生添加进队列,第一个数1添加到队列尾部,第二个数2添加到队列尾部,依次到第五个数5被淘汰,然后循环执行当队列的size为1的时候就执行完成了,输出。

  • 击鼓传花代码实现

 //击鼓传花
    function passGame(nameList,number){
        //1.创建一个队列结构
        let queue = new Queue();

        //2.将所有人依次加入队列
        for(let i= 0; i< nameList.length; i++){
            queue.enqueue(nameList[i]);
        }
        //开始数数字,不是number的话就加入到队列的末尾
        //如果是number的数字的话从队列删除掉
        //这个里面的所有人从队列前端删除掉,然后添加到队列的后面
        //3.number数字之前的人重新放入到队列的尾部
       while(queue.size() > 1){
            for(var i = 0; i < number - 1; i++){
            queue.enqueue(queue.dequeue());
            }
            //3.2number数字对应的人直接删除
            queue.dequeue();
        }

        //相当于每次将前四个一次删除并且插入到队列的末尾,然后将第五个真正删除
        
        //4.获取剩下的那个人
        let finalName = queue.front();
        let nameIndex = nameList.indexOf(finalName);
        return [finalName,nameIndex]
    }

    let nameList = ['小王','张三','李四','王五','赵六','钱七','周八','五九'];
    let number = 5;
    console.log(passGame(nameList,number));
    //["李四", 2]

7.优先级队列

1.普通队列和优先级队列比较

  • 普通队列:我们知道,普通的队列插入一个元素,数据会被放在后端,并且需要前面所有的元素都处理完成后才会处理插入的数据。

  • 优先级队列,在插入一个元素的时候会考虑当前数据的优先级

  • 和其他数据优先级进行比较

  • 比较完成后,可以得出这个元素在队列中正确的位置

  • 其他处理方式,和基本队列的处理方式一样

2.有限级队列主要考虑的问题

  • 每个元素不再只是一个数据,而且包含数据的优先级

  • 在添加方式中,根据优先级放入正确的位置

3.优先级队列的应用

  • 登机顺序,头等舱,商务舱登机顺序高于经济舱乘客。
  • 急诊科需要按照病人的病情排序候诊。
  • 计算机中我们也可以通过重新排序队列中任务的顺序
  • 比如某个线程处理的任务并不重要,我们可以通过优先级的大小,来决定该线程在队列中被处理的次序。

4.优先级队列(模拟根据数字排列,数字小的优先级高)

  • 1.数据项既包含数据也包含数据优先级
  • 2.插入方法: 当前队列没有元素的时候直接插入,当前队列有元素的时候,根据优先级插入

5.优先级队列的代码实现

   //封装优先级队列
    function PriorityQueue(){

        //为了保存数据,再封装一个类,内部类
        function QueueElement(element, priority){
            this,element = element;
            this.priority = priority;
        }

    //封装属性
    this.items = [];

    //1.实现插入方法
    PriorityQueue.prototype.enqueue = function(element, priority){
        //1.创建QueueElement对象
        let queueElement = new QueueElement(element, priority);

        //2.判断当前队列是否为空
        if(this.items.length == 0){
            this.items.push(queueElement);
        } else{
            let flag = false;
            for(let i =0 ; i< this.items.length; i++){
                if(queueElement.priority < this.items[i].priority){
                    this.items.splice(i,0,queueElement);
                    flag = true;
                    break;
                }
            }
            if(!flag){
                this.items.push(queueElement);
            }
        }
    }
        //2.从队列中删除前端元素
        PriorityQueue.prototype.dequeue = function(){
            return this.items.shift()
        }
        //3.查看前端的元素
        PriorityQueue.prototype.front = function(){
            return this.items[0];
        }
        //4.查看队列是否为空
        PriorityQueue.prototype.isEmpty = function(){
            return this.items.length == 0;
        }
        //5.查看队列中元素的个数
        PriorityQueue.prototype.size = function(){
            return this.items.length;
        }
        //6.toString方法
        PriorityQueue.prototype.toString = function(){
            let resultString = '';
            for(let i = 0; i < this.items.length; i++){
                resultString += this.items[i] + ',';
            }
            return resultString;
    }
    }
    let pq = new PriorityQueue();
    //1.插入元素
    pq.enqueue('abc',1);
    pq.enqueue('kjh',998);
    pq.enqueue('hig',100);
    pq.enqueue('def',10);
    pq.enqueue('kjh',1000);
    console.log(pq);

    //2.删除元素
    pq.dequeue();

    //3....
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值