开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
1 什么是队列?
-
队列是一种
先进先出(First In First Out,FIFO)的数据结构。其中是一组有序的数据项,遵循头部删除数据,尾部添加数据的原则。生活中的队列有哪些?排队买电影票、飞机票等这种都是先到先服务,当天买完了就没有了。队列也是一样先来先入队出队。如一组数据从左到右按顺序进行入队:1,3,1,4,5,2,0。 -
队列可以做什么?- push:在队列尾部添加元素。
- pop:在队列头部删除元素。
- peek:获取队列的第一个元素,也就是队头,不改变队列原有元素。
- isEmpty:判断队列是否为空。
-
队列的Javascript实现? -
以两个栈为例:定义两个数组stackIn和stackOut作为存储栈,stackIn栈临时存储push进来的值,stackOut存储真正队列的数据序列。每次存到stackIn中的值都会被添加到stackOut数组开头(也就是队尾),获取队头也就是获取stackOut栈顶的数据,这样就遵循了队列先进先出的原则了。
var MyQueue = function() { this.stackIn = [];// 临时存储数据元素队列 this.stackOut = [];// 真正存储数据元素队列 }; -
队列操作主要方法:对临时存储数组进行一一出栈添加到另一数组的开头,stackOut最后一个元素就是队头,数组的第一个元素就是队尾,符合队列的先进后出的原则。
MyQueue.prototype.fillStack = function(){ if(this.stackIn.length===0) return; while(this.stackIn.length){// 判断存储数据的栈 this.stackOut.unshift(this.stackIn.pop());// 在数组开头添加元素 } } -
每次添加元素都会对stackOut进行操作:
MyQueue.prototype.push = function(x) { this.stackIn.push(x); this.fillStack(); }; -
读取队头(改变原来数组):
this.stackOut.pop(); -
读取队头(不改变原来数组):
this.stackOut.slice(-1);;
2 什么是双端队列?
双端队列:类似生活中的双火车头,火车前后都可以添加火车头,也可以去掉车厢节。同样的道理队列的前后都可以添加或删除队列元素。
var MyCircularDeque = function(k) {
this.size=k;
this.circularDeque = [];
};
-
双端队列的实现: -
insertFront:在队列头部添加元素。
MyCircularDeque.prototype.insertFront = function(value) { if(this.isFull()){ return false; }else{ this.circularDeque.unshift(value); } return true; }; -
insertLast:在队列尾部添加元素。
MyCircularDeque.prototype.insertLast = function(value) { if(this.isFull()){ return false; }else{ this.circularDeque.push(value); } return true; }; -
deleteFront:在队列头部删除元素。
this.circularDeque.shift() -
deleteLast:在队列尾部删除元素。
this.circularDeque.pop() -
getFront:获取队列头部元素。
this.circularDeque[0] -
getRear:获取队列尾部元素。
this.circularDeque[this.circularDeque.length-1] -
isEmpty:判断队列是否为空。
-
isFull:判断队列元素是否已经达到队列最大限制长度了。
3 什么是循环队列?
-
循环队列:为了合理使用队列空间,通过head和tail指针控制队列添加或删除数据,初始的时候,head和tail都是指向队列索引0位置,当队列空间已经满了,head和tail又重新指回同一位置,怎么实现队列循环的呢?当tail指针已经指向了一圈了,此时队列还有空间,可以通过tail%size(队列长度)充分利用剩余空间。 -
当队列添加元素时,tail指针后移,head指针保持原有位置不变。
-
当队列删除元素时,head指针后移,tail指针保持原有位置不变。
-
当元素已经到达了队列满空间位置了,head指针与tail指针又重新组合了,此时tail = tail%size。
-
循环队列的实现: -
enQueue:添加元素,tail指针后移。
MyCircularQueue.prototype.enQueue = function (value) { if (this.isFull()) { return false; } else { this.circularQue[this.tail % this.size] = value; this.tail++; return true; } }; -
deQueue:删除元素,head指针后移。
MyCircularQueue.prototype.deQueue = function () { if (this.isEmpty()) { return false; } else { this.head++; } return true; }; -
Front:获取对头元素。
MyCircularQueue.prototype.Front = function () { if (this.isEmpty()) { return -1; } else { return this.circularQue[this.head% this.size]; } }; -
Rear:获取队尾元素。
MyCircularQueue.prototype.Rear = function () { if (this.isEmpty()) { return -1; } else { return this.circularQue[(this.tail-1)%this.size]; } }; -
isEmpty:判断当前队列是否为空。
MyCircularQueue.prototype.isEmpty = function () { return this.head === this.tail; }; -
isFull:判断当前队列空间是否已满。
MyCircularQueue.prototype.isFull = function () { if (this.tail - this.head === this.size) { return true; } return false; };