队列遵循先进先出原则。队列在尾部添加新元素,并从顶部移出元素,最新添加的元素必须排在队列的末尾。
ES5:
function Queue(){
let items = [];
// 向队列添加元素
this.enqueue = function(ele){
items.push(ele);
}
//从队列移出元素
this.dequeue = function(){
return items.shift();
}
// 查看队头元素
this.front = function(){
console.log(items[0]);
return items[0];
}
//获取队列长度
this.size = function(){
var len = items.length;
return len;
}
// 检查队列是否为空
this.isEmpty = function(){
return items.length == 0;
}
// 打印队列
this.print = function(){
console.log(items.toString());
}
}
测试:
var queue = new Queue();
queue.isEmpty();
queue.enqueue(1);
queue.enqueue(2);
queue.isEmpty();
queue.front(); //1
queue.print(); //1,2
queue.dequeue();
queue.print(); //2
ES6:
我们用一个WeakMap来保存私有属性items,并用闭包来封装Queue类
let Queue = (function(){
const items = new WeakMap();
class Queue{
constructor(){
items.set(this, []);
}
enqueue(ele){
let q = items.get(this);
q.push(ele);
}
dequeue(){
let q = items.get(this);
let res = q.shift();
console.log('出队',res);
return res;
}
front(){
let q = items.get(this, []);
console.log('f:',q[0]);
return q[0];
}
size(){
let q = items.get(this, []);
let len = q.length;
return len;
}
isEmpty(){
let q = items.get(this, []);
return q.length == 0;
}
print(){
let q = items.get(this, []);
console.log('print:',q.toString());
}
}
return Queue;
})();
测试:
var queue = new Queue();
queue.isEmpty();
queue.enqueue(1);
queue.enqueue(4);
queue.enqueue(3);
queue.isEmpty();
queue.front(); //1
queue.print(); //1,4,3
queue.dequeue(); //1
queue.print(); //4,3
优先队列
优先队列的元素添加和移出是基于优先级的。
实现一个优先队列,有两种选项:
(1)设置优先级,然后再正确的位置添加元素;
(2)用入列操作添加元素,然后按照优先级移出它们;
下面我将以第一种方法实现:
function PriorityQueue(){
let items = [];
function QueueElement(ele, priority){
this.ele = ele;
this.priority = priority;
}
this.enqueue = function(ele, priority){
let queueElement = new QueueElement(ele, 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.print = function(){
for(let i = 0;i < items.length; i++){
console.log(`${items[i].priority} - ${items[i].ele}`)
}
};
//其他方法和默认的Queue实现相同
}
测试:
let pQ = new PriorityQueue();
pQ.enqueue('tom',3);
pQ.enqueue('jack',2);
pQ.enqueue('John',2);
pQ.print(); //2-jack 2-John 3-tom
我在这里实现的优先队列称为最小优先队列(将优先级较小的元素放置在队列的最前面),还有最大优先队列(把优先级的值较大的元素放置在队列的最前面)。
循环队列
我们用一个实际例子来理解循环队列(击鼓传花游戏)
function Queue2(nameList, num){
let queue = new Queue();
let len = nameList.length;
for(let i = 0;i < len; 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 + '在击鼓传花游戏中被淘汰!!');
}
console.log("胜利者:"+ queue.dequeue());
return queue.dequeue();
}
测试:
let nameList = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N'];
Queue2(nameList, 5);
结果:
F在击鼓传花游戏中被淘汰!!
L在击鼓传花游戏中被淘汰!!
D在击鼓传花游戏中被淘汰!!
K在击鼓传花游戏中被淘汰!!
E在击鼓传花游戏中被淘汰!!
N在击鼓传花游戏中被淘汰!!
I在击鼓传花游戏中被淘汰!!
G在击鼓传花游戏中被淘汰!!
C在击鼓传花游戏中被淘汰!!
H在击鼓传花游戏中被淘汰!!
M在击鼓传花游戏中被淘汰!!
J在击鼓传花游戏中被淘汰!!
B在击鼓传花游戏中被淘汰!!
胜利者:A