学习JavaScript数据结构与算法(三)——队列

来源:互联网 发布:网店美工培训课程 编辑:程序博客网 时间:2024/05/21 17:39

队列是遵循FIFO(First In First Out,先进先出,也称为先来先服务)原则的一组有序的项。
队列在尾部添加新元素,并从顶部移除元素。
最新添加的元素必须排在队列的末尾。
在现实中,最常见的队列的例子就是排队,排在第一位的人先接受服务。

一、创建队列

function Queue () {    var items = [];    /*    enqueue(element(s))    向队列尾部添加一个或多个新的项     */    this.enqueue = function(element){        items.push(element);    };    /*    dequeue()    移除队列的第一(即排在队列最前面的)项,并返回被移除的元素     */    this.dequeue = function(){        return items.shift();    };    /*    front()    返回队列中第一个元素(最先被添加,也将是最先被移除的元素)    队列不做任何变动,不移除元素,只返回元素信息     */    this.front = function(){        return items[0];    };    /*    isEmpty()    如果队列中不包含任何元素,返回true,否则返回false     */    this.isEmpty = function(){        return items.length == 0;    };    /*    clear()    移除队列中的所有元素     */    this.clear = function(){        items = [];    };    /*    size()    返回队列的元素个数    和数组的length属性类似     */    this.size = function(){        return items.length;    };    /*    print()    辅助方法,将队列中的元素输出到控制台     */    this.print = function(){        console.log(items.toString());    };}

二、使用Queue类

var queue = new Queue();console.log(queue.isEmpty());  //输出true//添加一些元素queue.enqueue("John");queue.enqueue("Jack");queue.enqueue("Ben");queue.print();  //输出John,Jack,Benconsole.log(queue.size());  //输出3console.log(queue.isEmpty());  //输出falsequeue.dequeue();queue.print();  //输出Jack,Benqueue.dequeue();queue.print();  //输出Ben

输出结果如下:

使用Queue类

三、优先队列

元素的添加和移除是基于优先级的。
举个例子,医院的(急诊科)候诊室,医生会优先处理病情比较严重的患者。

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++) {                /*                当找到一个比要添加的元素的priority值更大(优先级更低)的项时,                就把新元素插入到它之前                (对于其他优先级相同,但是先添加到队列的元素,                同样遵循先进先出的原则)                 */                if (queueElement.priority < items[i].priority) {                    items.splice(i, 0, queueElement);                    added = true;                    break;                }            }            /*            如果要添加元素的priority值大于任何已有的元素,            把它添加到队列的末尾就行了             */            if (!added) {                items.push(queueElement);            }        }    };    /*其他方法与默认的Queue实现相同*/    this.dequeue = function(){        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 () {        var temp = [];        for(var i = 0; i < items.length; i++){            temp.push(items[i].element);        }        console.log(temp.toString());    };}

【注】处理添加元素的方法与默认的不一样外,还有print()方法也略有不同。
在默认的队列中,定义的items数组只存储了element,但是在优先队列中的items里,除了element,还有priority(优先级),这时候为了在控制台上只输出显示队列中的元素,就需要一个临时数组temp来存储element,具体实现看上面的代码。

测试代码如下:

var priorityQueue = new PriorityQueue();priorityQueue.enqueue("John", 2);priorityQueue.print();priorityQueue.enqueue("Jack", 1);priorityQueue.print();priorityQueue.enqueue("Ben", 1);priorityQueue.print();

第一个添加的元素是优先级为2的John,因为此前队列为空,所以它是队列中唯一的元素。
然后,添加优先级为1的Jack,由于Jack的优先级高于John,Jack就成了队列的第一个元素。
接下来,添加优先级为1的Ben,Ben的优先级高于John,所以在John前面;Ben的优先级和Jack相同,但Ben在Jack之后添加,所以Ben在Jack后面。

优先队列

四、循环队列——击鼓传花

在这个游戏中,孩子们围成一个圆圈,把花尽快传递给旁边的人,某一时刻传花停止,这个时候花在谁手里,谁就退出圆圈结束游戏,重复这个过程,直到只剩一个孩子(胜者)。

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());        }        //一旦传递次数达到给定的数字,拿着花的那个人就被淘汰了        eliminated = queue.dequeue();        console.log(eliminated + '在击鼓传花游戏中被淘汰。');    }    return queue.dequeue();}var names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl'];var winner = hotPotato(names, 7);console.log('胜利者:' + winner);

输出如下:

击鼓传花

原创粉丝点击