佇列資料結構
佇列遵循FIFO,先進先出原則的一組有序集合。佇列在尾部新增元素,在頂部刪除元素。在現實中最常見的佇列就是排隊。先排隊的先服務。(請大家文明排隊,不要插隊。)
建立佇列
實現包含以下方法的Queue類
- enqueue(element(s)):向佇列尾部新增一個(或多個)元素。
- dequeue():移除佇列的第一項,並返回移除的元素。
- front():返回佇列的第一個元素--最先被新增,最先被移除的元素。
- isEmpty():判斷佇列是否為空。
- size():返回佇列的長度。
1、簡單實現Queue類
// 佇列Queue類簡單實現
function Queue() {
let 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.size = function() {
return items.length;
};
}
複製程式碼
2、ES6語法實現Queue佇列類,利用WeakMap來儲存私有屬性items,並用外層函式(閉包)來封裝Queue類。
let Queue1 = (function() {
const items = new WeakMap();
class Queue1 {
constructor() {
items.set(this, []);
}
// 獲取佇列
getQueue() {
return items.get(this);
}
// 新增元素
enqueue (element) {
this.getQueue().push(element);
}
// 刪除元素
dequeue() {
return this.getQueue().shift();
}
// 返回佇列第一個元素
front() {
return this.getQueue()[0];
}
// 判斷佇列是否為空
isEmpty() {
return this.getQueue().length === 0;
}
// 返回佇列長度
size() {
return this.getQueue().length;
}
}
return Queue1;
})();
複製程式碼
優先佇列
元素的新增和刪除基於優先順序。常見的就是機場的登機順序。頭等艙和商務艙的優先順序高於經濟艙。實現優先佇列,設定優先順序。
// 優先列隊
function PriorityQueue() {
let items = [];
// 建立元素和它的優先順序(priority越大優先順序越低)
function QueueElement(element, priority) {
this.element = element;
this.priority = priority;
}
// 新增元素(根據優先順序新增)
this.enqueue = function(element, priority) {
let queueElement = new QueueElement(element, priority);
// 標記是否新增元素的優先順序的值最大
let added = false;
for (let i = 0; i < items.length; i++) {
if (queueElement.priority < items[i].priority) {
items.splice(i, 0, queueElement);
added = true;
break;
}
}
if (!added) {
items.push(queueElement);
}
};
// 刪除元素
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 (let i = 0; i < items.length; i++) {
console.log(`${items[i].element} - ${items[i].priority}`);
}
};
}
複製程式碼
迴圈佇列(擊鼓傳花)
// 迴圈佇列(擊鼓傳花)
function hotPotato(nameList, num) {
let queue = new Queue(); // {1}
for(let i =0; i< nameList.length; i++) {
queue.enqueue(nameList[i]); // {2}
}
let eliminted = '';
while(queue.size() > 1) {
// 把佇列num之前的項按照優先順序新增到佇列的後面
for(let i = 0; i < num; i++) {
queue.enqueue(queue.dequeue()); // {3}
}
eliminted = queue.dequeue(); // {4}
console.log(eliminted + '在擊鼓傳花遊戲中被淘汰');
}
return queue.dequeue(); // {5}
}
let names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl'];
let winner = hotPotato(names, 7);
console.log('獲勝者是:' + winner);
複製程式碼
實現一個模擬擊鼓傳花的遊戲,{1}利用佇列類,建立一個佇列。{2}把當前玩擊鼓傳花遊戲的所有人都放進佇列。{3}給定一個數字,迭代佇列,從佇列的開頭移除一項,新增到佇列的尾部(如遊戲就是:你把花傳給旁邊的人,你就可以安全了)。{4}一旦迭代次數到達,那麼這時拿著花的這個人就會被淘汰。{5}最後剩下一個人,這個人就是勝利者。