🏠 Home 

PushQueue

推入队列,循环数组实现

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/432936/1161000/PushQueue.js

/* exported PushQueue */
/**
* PushQueue
*
* 推入队列,循环数组实现。
* @template T 数据类型
* @version 1.1.2.20230313
* @author Laster2800
* @see {@link https://gitee.com/liangjiancang/userscript/tree/master/lib/PushQueue PushQueue}
*/
class PushQueue {
/** @type {number} 起始元素位置(指向起始元素后方) */
index = 0
/** @type {number} 队列长度 */
size = 0
/** @type {number} 最大长度 */
maxSize = 0
/** @type {T[]} 内部数据 */
data = null
/**
* @param {number} maxSize 队列的最大长度,达到此长度后继续推入数据,将舍弃队头处的数据
*/
constructor(maxSize) {
this.maxSize = maxSize
this.data = new Array(maxSize)
}
/**
* 设置推入队列的最大长度
* @param {number} maxSize 最大长度
*/
setMaxSize(maxSize) {
if (this.size > maxSize) {
this.size = maxSize
}
const data = this.toArray().reverse()
this.maxSize = maxSize
this.index = data.length
data.length = maxSize
this.data = data
}
/**
* 向队尾推入数据,若队列已达到最大长度,则舍弃队头处数据
* @param {T} value 推入队列的数据
*/
enqueue(value) {
this.data[this.index] = value
this.index += 1
if (this.index >= this.maxSize) {
this.index = 0
}
if (this.size < this.maxSize) {
this.size += 1
}
}
/**
* 将队头处的数据弹出
* @returns {T} 弹出的数据
*/
dequeue() {
if (this.size <= 0) return
let index = this.index - this.size
if (index < 0) {
index += this.maxSize
}
this.size -= 1
const r###lt = this.data[index]
delete this.data[index]
return r###lt
}
/**
* 获取第 `n` 个元素(范围 `[0, size - 1]`)
* @param {number} n 元素位置
* @returns {T} 第 `n` 个元素
*/
get(n) {
if (n < 0 || n >= this.size) return
let index = this.index - n - 1
if (index < 0) {
index += this.maxSize
}
return this.data[index]
}
/**
* 设置第 `n` 个元素的值为 `value`(范围 `[0, size - 1]`,且第 `n` 个元素必须已存在)
* @param {number} n 元素位置
* @param {T} value 要设置的值
* @returns {boolean} 是否设置成功
*/
set(n, value) {
if (n < 0 || n >= this.size) return false
let index = this.index - n - 1
if (index < 0) {
index += this.maxSize
}
this.data[index] = value
return true
}
/**
* 将推入队列以数组的形式返回
* @param {number} [maxLength=size] 读取的最大长度
* @param {number} [offset=0] 起始点
* @returns {Array<T>} 队列数据的数组形式
*/
toArray(maxLength = this.size, offset = 0) {
if (offset < 0) {
offset = 0
}
if (offset + maxLength > this.size) {
maxLength = this.size - offset
}
const ar = []
let start = this.index - offset
if (start < 0) {
start += this.maxSize
}
let end = start - maxLength
for (let i = start - 1; i >= end && i >= 0; i--) {
ar.push(this.data[i])
}
if (end < 0) {
end += this.maxSize
for (let i = this.maxSize - 1; i >= end; i--) {
ar.push(this.data[i])
}
}
return ar
}
/**
* 标准迭代器:`item`
* @returns {IterableIterator<T>}
*/
[Symbol.iterator]() {
const iterator = this.entries()
return {
next: () => {
const n = iterator.next()
if (!n.done) {
n.value = n.value[1]
}
return n
},
}
}
/**
* 迭代器:`[index, item]`
* @returns {IterableIterator<[index: number, item: T]>}
*/
entries() {
let current = this.index - 1
let end = this.index - this.size
return {
next: () => {
if (current < 0 && end < 0) {
current += this.maxSize
end += this.maxSize
}
if (current < end || current < 0) return { done: true }
const n = { value: [current, this.data[current]], done: false }
current -= 1
return n
},
[Symbol.iterator]() { return this },
}
}
}