要求
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。 Front: 从队首获取元素。如果队列为空,返回 -1 。 Rear: 获取队尾元素。如果队列为空,返回 -1 。 enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。 deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。 isEmpty(): 检查循环队列是否为空。 isFull(): 检查循环队列是否已满。
思路
假设队列长度k=4
定义一个长度为k+1的数组let Queue = Array(k+1)
定义头指针front与尾指针rear,以及k的值max
当向数组内添加元素:rear+1,删除元素:front+1
Front: 从队首获取元素。如果队列为空,返回 -1 。
先判断队列是否为空:this.isEmpty()
为truereturn -1,
为falsereturn this.Queue[this.front]
Rear: 获取队尾元素。如果队列为空,返回 -1 。
先判断队列是否为空:this.isEmpty()
为truereturn -1,
为falsereturn this.Queue[this.rear - 1]
尾指针的值 - 1 就是最后队尾元素的下标,但是有可能出现下图情况
所以我们需要加上数组的最大长度k+1即max+1,然后进行求余
即:(this.rear(0) - 1 + this.max(4) + 1) % (this.max(4) + 1)得到4,即上图的最后一个节点的1
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
先判断队列是否为满:this.isEmpty()
为truereturn false
为false
-
插入元素到最后一个节点:
this.Queue[this.rear] = value -
rear指针向后移动一步:
this.rear += 1,但是要记得求余数组的最大长度,不然rear的数会超过数组的最大长度,所以应该this.rear = (this.rear + 1 + this.max + 1) % (this.max + 1) -
return true告诉我们添加成功
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
先判断队列是否为空:this.isEmpty()
为truereturn false
为false移动头指针即可this.front+=1,不过也需求余,即this.front = (this.front + 1) % (this.max + 1)
isEmpty(): 检查循环队列是否为空。
检查是否为空,判断两个指针的值即可
所以我们只需判断this.rear - this.front是否为0
所以我们return this.rear - this.front == 0;即可
因为两指针唯一一次重合的情况,就是一个值都没有的情况
isFull(): 检查循环队列是否已满。
检查是否已满,判断两指针相差是否为k即可
即判断this.rear - this.front == this.max是否为true
但是有可能rear的值比front的值要小,即下图情况
所以我们需要求余
即(this.rear - this.front + this.max + 1) % (this.max + 1)
上图数据套入此计算中得出3,距离数组能存的最大值k(4)还差1,所以我们返回false
完整代码
var MyCircularQueue = function (k) {
// 定义一个数组
this.Queue = Array(k + 1);
// 创建一个头指针,一个尾指针
this.front = 0;
this.rear = 0;
// 数组最大容量
this.max = k;
};
/**
* @param {number} value
* @return {boolean}
*/
MyCircularQueue.prototype.enQueue = function (value) {
// 先判断是否已满
if (this.isFull()) return false;
// 添加元素
this.Queue[this.rear] = value;
// 尾指针往后走一步
this.rear = (this.rear + 1) % (this.max + 1);
return true;
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.deQueue = function () {
// 先判断是否为空
if (this.isEmpty()) return false;
// 头指针往后走一步即可删除
this.front = (this.front + 1) % (this.max + 1)
return true
};
/**
* @return {number}
*/
MyCircularQueue.prototype.Front = function () {
// 先判断是否为空
if (this.isEmpty()) return -1;
// 返回头指针的下标,就是第一个元素
return this.Queue[this.front];
};
/**
* @return {number}
*/
MyCircularQueue.prototype.Rear = function () {
// 先判断是否为空
if (this.isEmpty()) return -1;
// 返回尾指针的下标-1的值,就是最后一个元素
return this.Queue[(this.rear - 1 + this.max + 1) % (this.max + 1)];
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.isEmpty = function () {
// 判断头指针与尾指针的下标是否一致,一致,即数组为空
return this.rear - this.front == 0;
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.isFull = function () {
// 尾指针减头指针,得到的数是否等于k值,若等于k值,即数组已满
// 但尾指针有可能小于头指针,所以需要求余
return ((this.rear - this.front + this.max + 1) % (this.max + 1)) == this.max;
};