上一次我们已经学习了栈。今天我们来说一说队列。
队列和栈非常类似,都是非常容易理解的数据结构。队列是遵循先来先服务原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。
在现实中,最常见的队列的例子就是排队:
排在前面的会先被服务,不管是什么服务。概念的东西非常简单,在这里就不再多说了。
接下来声明一些队列可用的方法:
enqueue(elements):向队列尾部添加一个或多个新的项。
dequeue():移除队列的第一项,并返回被移除的元素。
front():返回队列中的第一项,队列不做任何改动。注意与dequeue的区别。
isEmpty():如果队列中不包含任何元素,返回true,否则返回false。
size():返回队列中包含的元素个数。
实现代码:
function Queue(){
var 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.clear = function(){
items = [];
}
this.size = function(){
return items.length;
}
this.print = function(){
console.log(items.toString());
}
}
队列有两个修改版,其一是优先队列。元素的操作是基于优先级的。现实中也有这样的例子,比如机场登机的顺序。头等舱和商务舱的优先级是要高于经济舱的;又或者医院总是会看病情比较严重的患者。
如何实现呢?设置优先级。
function PriorityQueue(){
var items = [];
function QueueElement(element , priority){ //声明一个包含元素和优先级的构造函数
this.element = element;
this.priority = priority;
}
this.enqueue = function(element , priority){
var queueElement = new QueueElement(element , priority);
if(this.isEmpty()){ //如果为空,直接入列
items.push(queueElement);
}else{
var added = false;
for(var 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);
}
}
}
}
}
其二是循环队列,现实生活中的例子有击鼓传花的游戏。在这个游戏中,孩子们围成一个圆圈,把花尽快地传递到旁边的人。某一时刻鼓声停止,就停止传递。花在谁手上,谁就退出圆圈游戏。直到只剩下一个孩子。实现起来也是比较简单的:
function hotPotato(nameList , num){
var queue = new Queue();
for(var i = 0 ; i < nameList.length ; i++){ //把全部人加入到队列中
queue.enqueue(nameList[i]);
}
var eliminated = '';
while(queue.size() > 1){
for(var i = 0 ; i < num ; i++){ //循环
queue.enqueue(queue.dequeue());
}
eliminated = queue.dequeue(); //到达传递次数,淘汰
console.log(eliminated + '被淘汰');
}
return queue.dequeue(); //最后一个胜利者
}
可以看到,不管是优先队列还是循环队列,都是基于Queue这个构造函数的。测试代码请移步到队列
OK,队列就讲到这里了。有什么问题欢迎留言,共同讨论,共同成长!
下一节聊稍微复杂的链表!但我还是要简单说。