解题思路
队列是遵行先进先出的策略,而循环队列则使用固定大小的数组,使得队列在数组未空的情况下,绕行数组添加元素或删除元素,采用双指针来指示不断变化的头部与尾部,目的是未了节省内存的空间。
代码
class MyCircularQueue {
queue: number[]; // 数组
length: number; // 数组长度
header: number = -1; // 初始化指针,头部
tail: number = -1; // 初始化指针,尾部
constructor(k: number) {
// 初始化队列的长度,并以undefined进行空填充
this.queue = new Array(k);
this.length = k;
}
// 在尾部添加一个元素
enQueue(value: number): boolean {
// 判断数组是否已满
if (this.isFull()) {
return false;
}
// 当头部的指针与尾部的指针都是-1,表示两指针第一次步进1
if (this.header === -1 && this.tail === -1) {
this.header += 1;
this.tail += 1;
} else {
this.tail += 1;
// 由于是循环队列,尾部指针的最大值不能超过数组的最大索引值,当超过最大索引值,需要重新指向0
this.tail = this.tail % this.length;
}
// 赋值永远在尾部
this.queue[this.tail] = value;
return true;
}
// 在头部删除一个元素
deQueue(): boolean {
// 如果数组为空,则必会删除失败
if (this.isEmpty()) {
return false;
}
// 删除动作永远在头部指针上
delete this.queue[this.header];
// 删除后需要将头部指针步进1
this.header += 1;
// 同理,循环队列的头部指针与尾部指针都需要循环绕行,不能大于最大索引值
this.header = this.header % this.length;
return true;
}
// 返回头部元素
Front(): number {
const empty = this.isEmpty();
if (empty) {
return -1;
}
return this.queue[this.header];
}
// 返回尾部元素
Rear(): number {
const empty = this.isEmpty();
if (empty) {
return -1;
}
return this.queue[this.tail];
}
// 是否为空
isEmpty(): boolean {
// 初始化 结果为空
let result = true;
// 当发现一个元素不为空,则此数组必不为空,跳出循环
for (let i = 0; i < this.queue.length; i++) {
if (this.queue[i] !== undefined) {
result = false;
break;
}
}
return result;
}
// 是否已满
isFull(): boolean {
// 初始化 结果为满
let result = true;
// 当发现一个元素为空,则此数组必然未满,跳出循环
for (let i = 0; i < this.queue.length; i++) {
if (this.queue[i] === undefined) {
result = false;
break;
}
}
return result;
}
}