题目
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
来源:力扣(LeetCode)
链接:leetcode.cn/problems/de…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意概括:
一个数组(非循环),把它设计成循环的,如果是链表的话就是设计成一个圈。然后去补充队列为循环时,去写一些 队列为空、为满、插入、删除、头部值、尾部值的函数。
分析一波
因为为了为空为满时,方便,所以多给了一个空间,也就是说,当还剩一个空间的时候,那么这个队列就满了。
front: 表示队列的头部也就是第一个元素的下标。
rear: 表示队尾的下一个元素的下标。(即下一个从队尾入队元素的位置)。(当初困惑点)
k: 队列的总空间,也就是最多能容纳的数量。
cnt: 队列的长度。
当队列为空时: front===rear。
当队列满时: (rear+1) % k===front. 还差一个元素空间的时候判定为满。 %一下是因为要取余,因为要设置成一个循环的,所以超过的部分就重新从头部数。(当初困惑点)
这个循环列表,它的某位置上的元素被删除,但是后面的添加进来的元素依旧可以去占位以及使用。
插入的话: 必须先要判断一下是为满,满的话就已插不进去了。
删除的话,就是head往后走一步,依旧是最先判断队列是否为空。是否头部删除。所以是head+1。
因为rear表示的是队尾下一个元素的下标,所以在求队尾元素值的时候,要rear-1, 因为怕溢出,所以也要取余。 因此:(rear-1 + k)%k。
注意点
这里为什么要+k?
因为:
如果rear在最开始的头部,那么它-1的话,那么它的下标就是-1,就出去了,
总不能给返回个-1求值吧, 必须得进入到圈内,
所以,
就需要rear -1 + k再去求余,如果rear不在最开始的头部而是个2,
然后总k是8,2-1+8=9,也会溢出,
所以求余,9%8=1。
事实上rear为2的上一个也确实是1。
实践,上代码
/**
* @param {number} k
*/
var MyCircularQueue = function (k) {
this.queue = new Array(k + 1);
this.head = 0;
this.rear = 0;
this.k = k+1;
};
/**
* @param {number} value
* @return {boolean}
*/
MyCircularQueue.prototype.enQueue = function (value) {
if (this.isFull()) return false;
this.queue[this.rear] = value;
// 这里rear有加1,还没等给queque里面去赋值,再次插入值的时候,先去判断是否为满,就会rear再次加1,这样就会始终少一个,导致不准确,错误的,所以多给一个空间的同时也要给k加一个1.
this.rear = (this.rear + 1) % this.k;
return true;
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.deQueue = function () {
if (this.isEmpty()) return false;
//没啥用了
// this.cnt--;
this.head = (this.head + 1) % this.k;
return true;
};
/**
* @return {number}
*/
MyCircularQueue.prototype.Front = function () {
if (this.isEmpty()) return -1;
return this.queue[this.head];
};
/**
* @return {number}
*/
MyCircularQueue.prototype.Rear = function () {
if (this.isEmpty()) return -1;
console.log(this.queue);
return this.queue[(this.rear - 1 + this.k) % this.k]
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.isEmpty = function () {
return this.head === this.rear;
//这是另外一种解法,也可行,如果这里不用这种那么前面的cnt计数也没啥用了,也节省了一个空间。
// return this.cnt === 0;
};
/**
* @return {boolean}
*/
MyCircularQueue.prototype.isFull = function () {
return this.head === (this.rear + 1) % this.k;
//这是另外一种解法,也可行,如果这里不用这种那么前面的cnt计数也没啥用了,也节省了一个空间。
// return this.cnt===this.k;
};
this.rear = (this.rear + 1) % this.k;
这里rear有加1,还没等给queque里面去赋值,再次插入值的时候,先去判断是否为满,就会rear再次加1,这样就会始终少一个,导致不准确,错误的,所以多给一个空间的同时也要给k加一个1.