JS 行列-优先行列、轮回行列

《进修JavaScript数据构造与算法》读书笔记。

行列是遵行FIFO(First In First Out, 先进先出)准绳的一组有序的项。行列再尾部增加新元素,并从顶部移除元素。

在实际中,最常见的行列的例子就是列队。

1.建立行列

如今,我们来建立一个类来示意一个行列。先从最基本的声明类最早:

function Queue(){
    // 这里是属性和要领
}

起首,须要一个用户存储行列中元素的数据构造,我们能够运用数组。

var items = [];

接下来,声明一些行列可用的要领:

  • enqueue(element(s)):进队,向行列尾部增加一个(或多个)新项。

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

  • front():返回行列中第一个元素-最早被增加,也会是最早被移除的元素。(只返回,不移除)。

  • isEmpty():假如行列为空,返回true,不然,返回false。

  • size():返回行列的长度。

起首,我们来完成enqueue的要领,这个要领担任向行列中增加新元素。只能是增加到行列的尾部。

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

接下来要完成的是dequeue要领,这个要领担任从行列移除项。因为行列遵照的是先进先出准绳,所以最早移除的就是最早增加的,元素是排在数组的第一位。

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

只要enqueue要领和dequeue要领能够增加和移除元素,如许就确保了Queue类遵照先进先出准绳。
如今来为我们的类完成一些分外的辅佐要领:

    // front():返回行列中第一个元素
    this.front = function() {
        return items[0];
    }
    
    // isEmpty():假如行列为空,返回true,不然,返回false
    this.isEmpty = function() {
        return items.length === 0;
    }
    
    // size():返回行列的长度
    this.size = function() {
        return items.length;
    }

完成,我们的Queue类完成好了,如今来看看Queue完全的完成是怎样的:

function Queue() {
    var items = [];
    
    this.enqueue = function(element) {
        items.push(element);
    }
    
    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() {
        console.log(items.toString());
    }
}

2.运用Queue类

var queue = new Queue();
console.log(queue.isEmpty()); // 输出 true
queue.enqueue('John');        // 增加元素 John
queue.enqueue('Jam');         // 增加元素 Jam
queue.enqueue('Camila');      // 增加元素 Camila
queue.print();
console.log(queue.size);      // 输出 3
console.log(queue.isEmpty);   // 输出 false
queue.dequeue();              // 移除元素
queue.dequeue();            
queue.print();

运转上面的代码,我们能够看出,我们已完成了行列,遵照了先入先出准绳。

3.优先行列

上面我们已完成了一个行列,如今,逐渐深切,我们来看看什么是优先行列。

优先行列是默许行列的变种,它的元素的增加和移除是基于优先级的。一个实际的例子就是病院的(急诊科)候诊室。大夫会优先处置惩罚病情比较严重的患者。

完成一个优先行列,有两种挑选:设置优先级,然后在准确的位置增加元素;或许用默许入列操纵增加元素,任何依据优先级移除它们。下面,我们将会在准确的位置增加元素,任何用默许你的出列操纵。

    function PriorityQueue() {
        var items = [];
        
        // {1}
        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);  // {2}
            } else {
                var added = false;
                for(var i = 0; i < items.length; i++) {
                    if(queueElement.priority < items.[i].priority) {
                        items.splice(i, 0, queueElement);    // {3}
                        added = true;
                        break;
                    }
                }
                if(!added) {    // {4}
                    items.push(queueElement);
                }
            }
        }
        
        // 其他要领与默许行列一样
    }

我们建立了一个特别的元素(行{1}),这个元素包含了要增加到行列的元素及其优先级。

假如行列为空,则直接将元素入列(行{2})。不然,就要举行比较。当找到一个比要增加的元素的priority值更大(优先级更低)时,就将元素插进去到它之前(行{3})。

假如要增加的元素的priority指大于任何已有的元素,则直接将其增加到行列的末端(行{4})。

var priorityQueue = new PriorityQueue();
priorityQueue.enqueue('John', 2);
priorityQueue.enqueue('Jam', 1);
priorityQueue.enqueue('Sam', 1);
priorityQueue.print();

至此,我们已完成了优先行列,下面,将再引见一种行列——轮回行列

4.轮回行列——伐鼓传花

轮回行列是默许行列的另一种修改版,什么是轮回行列呢?举个实际中的例子,记得小时刻玩过的传花游戏吗?
几个孩子围成一圈,最早伐鼓了,孩子就把花尽快地通报给旁边的人,某一时刻鼓声住手了,传花也就住手了,这个时刻花落在谁手上,谁就被镌汰。鼓声响起,继续传花,云云轮回,直至只剩下一个孩子,即胜者。

function hotPotato(namelist, num) {
    var queue = new Queue();
    for (var i = 0; i < namelist.length; i++) {     // {1}
        queue.enqueue(namelist[i]);
    }
    var eliminated = "";
    while (queue.size() > 1) {                 // {2}
        for (var i = 0; i < num; i++) {
            queue.enqueue(queue.dequeue());    // {3}
        }
        eliminated = queue.dequeue();    // {4}
        console.log(eliminated + "在伐鼓传花游戏中被镌汰");
    }
    return queue.dequeue();    // {5}
}
var names = ['john', 'jack', 'camila', 'ingrid', 'carl'];
var winner = hotPotato(names, 7);
console.log("胜利者: " + winner);      //john

起首,先把名单增加到行列内里(行{1})。

当行列的的长度大于1的时刻(行{2}),依据指定的一个数字(num)迭代行列,将行列的头一个移除并将其增加到队尾(行{3})。

一旦通报次数到达给定的数字,则删除此时的行列第一项(行{4}),即拿开花的那个人,他将被镌汰。

云云轮回,直至行列的长度即是1,返回胜者(行{5})。

5.小结

经由过程这篇文章的引见,我们学会了如何用数组构造出行列的类。同时,还控制了很有名的优先行列、轮回行列这两种构造。

附:
JavaScript数据构造和算法系列:
JS 栈

JavaScript设想形式系列:
JavaScript设想形式之战略形式
JavaScript设想形式之宣布-定阅形式(观察者形式)-Part1

    原文作者:wuweisen
    原文地址: https://segmentfault.com/a/1190000007724033
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞