队列的介绍
队列是一种遵从先进先出(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();
}