javascript 隊列(queue)算法與說明

隊列的介紹

隊列是一種遵從先進先出(FIFO)先來先服務的有序的項,就是喝茶拿號模式(最前的號,最先進去)。隊列在尾部添加新元素,並從頂部移除元素。最新添加的元素必須排在隊列的末尾。


隊列算法實例

1.我有三個元素John,Jack,Camila,按循序添加三個元素,就會得到下圖的一個隊列。



2.隊列刪除。

let queue = new Queue()
queue.enqueue('John')
queue.enqueue('Jack')
queue.enqueue('Camila')//John,Jack,Camila添加完畢隊列
queue.dequeue()//刪除一個元素 Jack,Camila
queue.dequeue()//刪除一個元素 Camila




ES6隊列實現代碼:

let Queue = (function () {

    const items = new WeakMap();//WeakMap對象是密鑰/值對的集合,其中密鑰被弱引用。鍵必須是對象,值可以是任意值。

    class Queue {

        constructor () {
            items.set(this, []);
        }

        enqueue(...element) {//向隊列尾部添加一個(或多個)新的項
            let q = items.get(this);
            q.push(...element);
        }

        dequeue() {//移除隊列的第一個(排在隊列最前面的)項,並返回被移除的元素。
            let q = items.get(this);
            let r = q.shift();
            return r;
        }

        front() {//返回隊列中第一個元素——最先被添加,也將是最先被移除的元素。隊列不做任何變動(不移除元素,只返回元素信息)
            let q = items.get(this);
            return q[0];
        }

        isEmpty(){//如果隊列中不包含任何元素,返回true,否則返回false。
            return items.get(this).length == 0;
        }

        size(){//返回隊列包含的元素個數,與數組的length屬性類似。
            let q = items.get(this);
            return q.length;
        }

        clear(){//清空隊列裏面的元素。
            items.set(this, []);
        }

        print(){//打印隊列爲String到控制檯
            console.log(this.toString());
        }

        toString(){//輸出隊列以String模式。
            return items.get(this).toString();
        }
    }
    return Queue;
})();

let queue = new Queue();//實例化



隊列的種類

在計算機科學中,隊列在原先的版本中,有幾種修改版本分別是優先隊列循環隊列


優先隊列

優先隊列,就是元素添加和移除是基於優先級的。就是在原來的排隊中在分優先級。現實例子就是醫院排隊看病,病情嚴重的優先排在前面進行治療。

let priorityQueue = new PriorityQueue()
priorityQueue.enqueue('John'2)//添加元素和優先級
priorityQueue.enqueue('Jack'1)
priorityQueue.enqueue('Camila'1)//Jack,Camila,John添加完畢隊列




ES6代碼實例:

let PriorityQueue = (function () {

    class QueueElement {//優先隊列元素包含(元素,優先級)
        constructor(element, priority){
            this.element = element;
            this.priority = priority;
        }
    }

    const items = new WeakMap();

    class PriorityQueue { 

        constructor () {
            items.set(this, []);
        }

        enqueue(element, priority){//主要修改,在新元素添加的時候,放到優先級相同位置,但是先添加到隊列的元素,我們同樣遵從先進先出的原則。
            let queueElement = new QueueElement(element, priority);

            let q = items.get(this);

            let added = false;
            for (let i=0; i<q.length; i++){
                if (queueElement.priority < q[i].priority){
                    q.splice(i,0,queueElement);
                    added = true;
                    break;
                }
            }
            if (!added){
                q.push(queueElement);
            }

            items.set(this, q);
        };

        dequeue() {
            let q = items.get(this);
            let r = q.shift();
            items.set(this, q);
            return r;
        }

        front() {
            let q = items.get(this);
            return q[0];
        }

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

        size(){
            let q = items.get(this);
            return q.length;
        }

        clear(){
            items.set(this, []);
        }

        print(){
            let q = items.get(this);
            for (let i=0; i<q.length; i++){
                console.log(`${q[i].element}  - ${q[i].priority}`);
            }
        };
    }
    return PriorityQueue;
})();


let priorityQueue = new PriorityQueue();



循環隊列-擊鼓傳花

循環隊列。現實例子就是擊鼓傳花(Hot Potato),在遊戲中,孩子們圍着圓圈,把花儘快地傳遞給旁邊的人。某一時刻傳花停止,這個時候花在誰手裏,誰就退出圓圈結束遊戲。重複這個過程,直到只剩一個孩子(勝利)。

let names = ['John','Jack','Camila','Ingrid','Carl'];
let winner = hotPotato(names, 7);
console.log(winner+"勝利者"//Camila被淘汰。
//Jack被淘汰。
//Carl被淘汰。
//Ingrid被淘汰。
//John勝利者


ES6循環隊列實例:

let Queue = (function () {

    const items = new WeakMap();//WeakMap對象是密鑰/值對的集合,其中密鑰被弱引用。鍵必須是對象,值可以是任意值。

    class Queue {

        constructor () {
            items.set(this, []);
        }

        enqueue(...element) {//向隊列尾部添加一個(或多個)新的項
            let q = items.get(this);
            q.push(...element);
        }

        dequeue() {//移除隊列的第一個(排在隊列最前面的)項,並返回被移除的元素。
            let q = items.get(this);
            let r = q.shift();
            return r;
        }

        front() {//返回隊列中第一個元素——最先被添加,也將是最先被移除的元素。隊列不做任何變動(不移除元素,只返回元素信息)
            let q = items.get(this);
            return q[0];
        }

        isEmpty(){//如果隊列中不包含任何元素,返回true,否則返回false。
            return items.get(this).length == 0;
        }

        size(){//返回隊列包含的元素個數,與數組的length屬性類似。
            let q = items.get(this);
            return q.length;
        }

        clear(){//清空隊列裏面的元素。
            items.set(this, []);
        }

        print(){//打印隊列爲String到控制檯
            console.log(this.toString());
        }

        toString(){//輸出隊列以String模式。
            return items.get(this).toString();
        }
    }
    return Queue;
})();


function hotPotato (nameList, num){
    let queue = new Queue();

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

    let eliminated = '';
    while (queue.size() > 1){
        for (let i=0; i<num; i++){
            queue.enqueue(queue.dequeue());//從隊列開頭移除一項,再將其添加到隊列末位。
        }
        eliminated = queue.dequeue();//傳遞次數達到指定的數字,那個人淘汰。
        console.log(eliminated + '被淘汰。');
    }

    return queue.dequeue();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章