JavaScript隊列

隊列

隊列是遵循FIFO(First In First Out,先進先出)的一組有序的項。在計算機科學中,最多見的是打印隊列,好比我須要打印五份文檔,就先打開每一個文檔,再點擊打印按鈕,則每個文檔都會被髮送到打印隊列。第一個發送到打印隊列的文檔會首先打印,依次類推,直到打印完全部五篇文檔。此外,須要說明一下的是,在linux中,FIFO是一種特殊的文件類型,也便是咱們熟知的」管道「,它主要的目的在於解決多個程序訪問同一個文件形成的錯誤問題,使用ls命令時,該類文件的第一個屬性爲p。詳細請看附錄的man fifo圖。
node

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.linux

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();

從下面的運行結果應該能夠看出,隊列的這個特性。ide

固然這裏說的隊列是默認隊列,下面說說其餘的隊列。函數

優先隊列(最小優先隊列)

數據結構某種意義上是爲了抽象咱們的現實生活而服務的。優先隊列至關於在普通隊列的基礎上增長了一個優先級的屬性,這就比如坐飛機的時候,頭等艙的乘客的優先級高於經濟艙的乘客的優先級同樣。this

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.spa

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();

運行結果以下:
設計

注意上面代碼中的splice函數的使用方式。第一個參數指定即將開始處理的數組索引。第二個參數爲正數的時候就刪除相應個數的元素,在原來的基礎之上添加第三個參數以及其後的任意多個元素;當第二個參數是0的時候則不刪除任何的元素,而只在原來的基礎之上添加第三個參數以及其後的任意多個元素,請看下面的栗子:code

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);//剩者爲王

運行結果以下:

附錄

man fifo

相關文章
相關標籤/搜索