题目描述
设计一个支持如下操作的循环队列
- MyCircularQueue(k): 构造器,设置队列长度为 k 。
- Front: 从队首获取元素。如果队列为空,返回 -1 。
- Rear: 获取队尾元素。如果队列为空,返回 -1 。
- enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
- deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
- isEmpty(): 检查循环队列是否为空。
- isFull(): 检查循环队列是否已满。
代码分析
构造器
仅实现构造器需求,设置一个list = new Array(x)即可
head 用来存储队列的头元素(可以用来出队列的时候处理指向)
tail 用来存储队列的尾元素(追加元素时候处理,读取顶部元素时候处理,读取队尾元素)
count 用来存储总的元素数量(可以用来判断元素有没有满,也可以用来对比元素有没有空)
max 用来存储队列的最大长度
var MyCircularQueue = function (k) {
this.list = new Array(k);
this.head = 0; // 头指针
this.tail = 0; // 尾指针
this.count = 0; // 元素数量
this.max = k;
};
复制代码
判断队列是否为空
为空即元素数量为0
MyCircularQueue.prototype.isEmpty = function () {
return this.count === 0;
};
复制代码
判断队列是否满员isFull
满员即 max === count
MyCircularQueue.prototype.isFull = function () {
return this.count === this.max;
};
复制代码
从队首获取元素Front
如果为空则返回-1
MyCircularQueue.prototype.Front = function () {
if (this.isEmpty()) return -1;
return this.list[this.head]; // 返回顶部元素
};
复制代码
返回队尾元素Rear
队尾元素可以用if来判断,如果tail为0,则说明队尾元素为列表尾部,其他情况则队尾元素为tail-1个元素
也可以使用公式
(this.tail - 1 + this.max) % this.max
MyCircularQueue.prototype.Rear = function () {
if (this.isEmpty()) return -1;
// if (tail === 0) {
// tail = this.max - 1;
// } else {
// tail -= 1;
// }
return this.list[(this.tail - 1 + this.max) % this.max];
};
复制代码
入队enQueue
入队满了则return false
入队则尾指针对应值为 value
count + 1
尾指针后移,且到最后一位值循环从0开始
最终返回 true
MyCircularQueue.prototype.enQueue = function (value) {
if (this.isFull()) return false;
this.list[this.tail] = value;
this.count += 1; // 多了一个元素
this.tail = (this.tail + 1) % this.max; // 尾指针更新
return true;
};
复制代码
出队deQUeue
出队空了则return false
出队则头部指针被设为空,且头部指针为下一个元素,当头部指针为最后一个元素时,从头开始
同样思路的简易公式
(this.head + 1)%this.max
同时 count - 1
且return true
MyCircularQueue.prototype.deQueue = function () {
if (this.isEmpty()) return false;
this.list[this.head] = null;
this.head = (this.head + 1) % this.max;
this.count -= 1;
return true;
};
复制代码
以上为设计循环队列的思路分析,实现方式为线性结构,空间复杂度稍微偏高,但是时间复杂度以及理解难度十分友好,非常有利于我们掌握队列这种数据结构,大家加油鸭~~~