隊列的介紹
隊列是一種遵從先進先出(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();
}