JavaScript队列

Stella981
• 阅读 872

队列

队列是遵循FIFO(First In First Out,先进先出)的一组有序的项。在计算机科学中,最常见的是打印队列,比如我需要打印五份文档,就先打开每个文档,再点击打印按钮,则每一个文档都会被发送到打印队列。第一个发送到打印队列的文档会首先打印,依次类推,直到打印完所有五篇文档。此外,需要说明一下的是,在linux中,FIFO是一种特殊的文件类型,也即是我们熟知的”管道“,它主要的目的在于解决多个程序访问同一个文件造成的错误问题,使用ls命令时,该类文件的第一个属性为p。详细请看附录的man fifo图。

A queue is an example of a linear data structure, or more abstractly a sequential collection. Queues provide services in computer science, transport, and operations research where various entities such as data, objects, persons, or events are stored and held to be processed later.

js当中是怎样定义队列的呢?实质上可以利用数组的一些特性,封装成一个队列类来实现。请看:

function Queue() {//声明这个队列类的属性和方法

    var items = [];

    this.enqueue = function(element){//入列
        items.push(element);
    };

    this.dequeue = function(){//出列,shift() 方法用于把数组的第一个元素从其中删除并返回第一个元素的值。
        return items.shift();
    };

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

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

    this.clear = function(){
        items = [];
    };

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

    this.print = function(){
        console.log(items.toString());
    };
}

Quene和Stack很像,唯一的不同就是dequeue方法和front方法,这是FIFO和LIFO的设计原则不一致导致的。具体是怎样的所谓“最先入列的元素同时最先出列”呢?来看几个栗子吧:

var queue = new Queue();
console.log(queue.isEmpty()); 
queue.enqueue("John");
queue.enqueue("Jack");
queue.print();
queue.enqueue("Camila");
queue.print();
console.log(queue.size()); 
console.log(queue.isEmpty());
queue.dequeue();
queue.dequeue();
queue.print();

从下面的运行结果应该可以看出,队列的这个特性。

JavaScript队列

当然这里说的队列是默认队列,下面说说其他的队列。

优先队列(最小优先队列)

数据结构某种意义上是为了抽象我们的现实生活而服务的。优先队列相当于在普通队列的基础上增加了一个优先级的属性,这就好比坐飞机的时候,头等舱的乘客的优先级高于经济舱的乘客的优先级一样。

In computer science, a priority queue is an abstract data type which is like a regular queue or stack data structure, but where additionally each element has a "priority" associated with it.

function PriorityQueue() {

    var items = [];

    function QueueElement (element, priority){
        this.element = element;
        this.priority = priority;
    }

    this.enqueue = function(element, priority){
        var queueElement = new QueueElement(element, priority);

        if (this.isEmpty()){
            items.push(queueElement);
        } else {
            var added = false;
            for (var i=0; i<items.length; i++){
                if (queueElement.priority < items[i].priority){
                    items.splice(i,0,queueElement);
                    added = true;
                    break;
                }
            }
            if (!added){//进入这里就说明优先级的数值最大,其优先级也最低,
                        //注意这里描述的是最小优先队列,即1
                        //的优先级最大,其他的随着priority值的增大,对应的优先级其实是越小的。
                items.push(queueElement);
            }
        }
    };//The splice method modifies arrayObj by removing the specified 
    //number of elements from position 
    //start and inserting new elements. 
    //The deleted elements are returned as a new Array object.

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

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

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

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

    this. print = function(){
        for (var i=0; i<items.length; i++){
            console.log(items[i].element + ' - ' + items[i].priority);
        }
    };
}

var priorityQueue = new PriorityQueue();
priorityQueue.enqueue("John", 2);
priorityQueue.enqueue("Jack", 1);
priorityQueue.enqueue("Camila", 1);
priorityQueue.enqueue("Maxwell", 2);
priorityQueue.enqueue("Ana", 3);
priorityQueue.print();

运行结果如下:

JavaScript队列

注意上面代码中的splice函数的使用方式。第一个参数指定即将开始处理的数组索引。第二个参数为正数的时候就删除相应个数的元素,在原来的基础之上添加第三个参数以及其后的任意多个元素;当第二个参数是0的时候则不删除任何的元素,而只在原来的基础之上添加第三个参数以及其后的任意多个元素,请看下面的栗子:

var arr = new Array("4", "11", "2", "10", "3", "1");
arr.splice(2, 2, "21", "31");
document.write(arr);// Output: 4,11,21,31,3,1

循环队列

利用前面已经定义过的队列,稍作修改,就实现一个新版本的队列——循环队列(Circular Queue)。

Circular queue is a linear data structure. It follows FIFO principle. In circular queue the last node is connected back to the first node to make a circle. Circular linked list follow the First In First Out principle. Elements are added at the rear end and the elements are deleted at front end of the queue.

循环队列好比是一个环,front和end是相连的,按照特定的次序(逆时针或者顺时针)进行遍历,接下来的代码模拟了一个hot potato游戏的逻辑,它揭示了循环队列的内涵。代码如下:

function hotPotato (nameList, num){

    var queue = new Queue();

    for (var i=0; i<nameList.length; i++){
        queue.enqueue(nameList[i]);
    }

    var eliminated = '';
    while (queue.size() > 1){
        for (var i=0; i<num; i++){
            queue.enqueue(queue.dequeue());//循环num次,将检索出来的那个元素放到最末尾(end)
        }
        eliminated = queue.dequeue();
        //循环一次之后就把这一轮循环结束时的front元素给删除(kick out)
        //此时队列的成员会逐渐减少。
        console.log(eliminated + ' was eliminated from the Hot Potato game.');
    }

    return queue.dequeue();
}

var names = ['John','Jack','Camila','Ingrid','Carl'];
var winner = hotPotato(names, 7);
console.log('The winner is: ' + winner);//剩者为王

运行结果如下:

JavaScript队列

附录

man fifo

JavaScript队列

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
LinkedBlockingQueue 介绍
LinkedBlockingQueue是一个基于已链接节点的、范围任意的blockingqueue。此队列按FIFO(先进先出)排序元素。队列的头部是在队列中时间最长的元素。队列的尾部是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可
Easter79 Easter79
3年前
TypeScript实现队列与双端队列
前言队列作为一种数据结构,在现实生活中它可应用于电影院、自助餐厅等场合,排在第一个的人会先接受服务。在计算机应用领域里,多个文档的打印就是一个队列,排在第一的文档会先执行打印操作。本文将用TypeScript实现队列与双端队列这两种数据结构,并用其解决计算机科学领域中的两道经典题,欢迎各位感兴趣的开发者阅读本文。队列的实现
Stella981 Stella981
3年前
PriorityBlockingQueue 介绍
PriorityBlockingQueue是一个基于优先级堆的无界的并发安全的优先级队列(FIFO),队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的Comparator进行排序,具体取决于所使用的构造方法。实现原理PriorityBlockingQueue通过使用堆这种数据结构实现将队列中的元素按照某种排序规则进行排序,从而改变先进先
Stella981 Stella981
3年前
ConcurrentQueue队列的基本使用方式
 队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。  ConcurrentQueue<T队列是一个高效的线程安全的队列,是.NetFramework4.0,System.Collections.Concurren
Stella981 Stella981
3年前
RocketMQ查询死信队列中的消息内容【实战笔记】
说明RocketMQ中当重试消息超过最大重试次数(默认16次),会被发送到%DLQ%开头的死信队列,默认死信队列为只写权限。在有些情况下,想看看死信队列里的内容。1.更改死信队列权限bin/mqadminupdateTopicPermcClusterBt%DLQ%onlin
Wesley13 Wesley13
3年前
PHP优先级队列
优先级队列首先,我们要了解一下什么叫队列:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。从定义来看,队列是无法更改顺序的线性集合。线性集合一般有几种规则:先进先出(队
菜园前端 菜园前端
1年前
什么是队列
原文链接:什么是队列?队列是一种遵循先进先出原则的有序集合,添加新元素的一端称为队尾,另一端称为队首。实现功能在JavaScript中没有队列,但是可以通过Array实现队列的所有功能enqueue()入队dequeue()出队top()获取队首值size