环形队列
作用
可以将数组重复利用,只要队列中的元素少于 最大长度 -1 , 那么就可以一直往队列中存放数据,对于一个固定的容量,实现先进先出,并且会频繁的存入和取出,就可以节省很大的性能消耗
- 队列中 需要
队列起始的位置
队列结束的位置
队列容量限制
队列是否为空
队列是否填充满了
队列的长度结算
往队列添加元素
从队列取出元素
首先我们用的队列会将数组的最后一个元素空出来,不存放任何元素,方便计算
根据图解 得出一个通用的计算容量的公式:通过移动开始索引和结束索引 完成数组的复用
export default class CricleArrayQueue<T>{
private maxSize: number; // 队列最大长度
private headIdx: number; // 指向队列在数组的起始位置
private tailIdx: number; // 指向队列最后一个元素的前一个位置
private arr: Array<T>; // 数组
constructor(_maxSize: number) {
this.maxSize = _maxSize;
this.headIdx = 0;
this.tailIdx = 0;
this.arr = new Array<T>(_maxSize);
}
public isEmpty(): boolean {
return this.headIdx == this.tailIdx;
}
public isFull(): boolean {
return (this.tailIdx + 1) % this.maxSize == this.headIdx;
}
public push(data: T | T[]): boolean {
if (this.isFull()) {
console.log("队列已满");
return false;
} else {
if (data instanceof Array) {
let index = 0;
while (data[index] && !this.isFull()) {
this.arr[this.tailIdx] = data[index++];
this.tailIdx = (this.tailIdx + 1) % this.maxSize;
}
} else {
this.arr[this.tailIdx] = data;
// 将队列中下一个放入元素的位置计算出来
this.tailIdx = (this.tailIdx + 1) % this.maxSize;
}
}
}
public shift(): T {
if (this.isEmpty()) {
console.log("队列为空---");
return undefined;
}
let value = this.headIdx;
// 将队列下一次取出的位置结算出来
this.headIdx = (this.headIdx + 1) % this.maxSize;
return this.arr[value];
}
public showArr(): void {
console.log("打印环形队列");
let size = this.Size;
let str = "";
for (let index = this.headIdx; index < this.headIdx+size; index++) {
str += " " + this.arr[index % this.maxSize];
}
console.log(str);
}
/** 容量计算 */
public get Size(): number {
return (this.tailIdx + this.maxSize - this.headIdx) % this.maxSize;
}
}
总结
环形队列难度在于容量的计算和队列起始位置和结束位置在存入和取出时的转换,才能够做到循环使用数组, 对于一个特殊需求的使用环境才可能用的上。