* @typeParam T - Type of queue items.
*/
export class Queue<T> {
- private items: Record<number, T>
- private head: number
- private tail: number
- private max: number
+ private items: T[]
+ private offset: number
+ public size: number
+ public maxSize: number
public constructor () {
- this.items = {}
- this.head = 0
- this.tail = 0
- this.max = 0
- }
-
- /**
- * Get the size of the queue.
- *
- * @returns The size of the queue.
- * @readonly
- */
- public get size (): number {
- return this.tail - this.head
- }
-
- /**
- * Get the maximum size of the queue.
- *
- * @returns The maximum size of the queue.
- * @readonly
- */
- public get maxSize (): number {
- return this.max
+ this.items = []
+ /** The size of the queue. */
+ this.size = 0
+ this.offset = 0
+ /** The maximum size of the queue. */
+ this.maxSize = 0
}
/**
* @returns The new size of the queue.
*/
public enqueue (item: T): number {
- this.items[this.tail] = item
- this.tail++
- if (this.size > this.max) this.max = this.size
+ this.items.push(item)
+ ++this.size
+ if (this.size > this.maxSize) {
+ this.maxSize = this.size
+ }
return this.size
}
* @returns The dequeued item or `undefined` if the queue is empty.
*/
public dequeue (): T | undefined {
- if (this.size <= 0) return undefined
- const item = this.items[this.head]
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
- delete this.items[this.head]
- this.head++
- if (this.head === this.tail) {
- this.head = 0
- this.tail = 0
+ if (this.size <= 0) {
+ return undefined
}
+ const item = this.items[this.offset]
+ if (++this.offset * 2 >= this.items.length) {
+ this.items = this.items.slice(this.offset)
+ this.offset = 0
+ }
+ --this.size
return item
}
/**
* Peek at the first item.
+ *
+ * @returns The first item or `undefined` if the queue is empty.
*/
public peek (): T | undefined {
- if (this.size <= 0) return undefined
- return this.items[this.head]
+ if (this.size <= 0) {
+ return undefined
+ }
+ return this.items[this.offset]
}
}
let rtSize = queue.enqueue(1)
expect(queue.size).toBe(1)
expect(rtSize).toBe(queue.size)
- expect(queue.head).toBe(0)
- expect(queue.tail).toBe(1)
- expect(queue.max).toBe(1)
- expect(queue.items).toStrictEqual({ 0: 1 })
+ expect(queue.offset).toBe(0)
+ expect(queue.maxSize).toBe(1)
+ expect(queue.items).toStrictEqual([1])
rtSize = queue.enqueue(2)
expect(queue.size).toBe(2)
expect(rtSize).toBe(queue.size)
- expect(queue.head).toBe(0)
- expect(queue.tail).toBe(2)
- expect(queue.max).toBe(2)
- expect(queue.items).toStrictEqual({ 0: 1, 1: 2 })
+ expect(queue.offset).toBe(0)
+ expect(queue.maxSize).toBe(2)
+ expect(queue.items).toStrictEqual([1, 2])
rtSize = queue.enqueue(3)
expect(queue.size).toBe(3)
expect(rtSize).toBe(queue.size)
- expect(queue.head).toBe(0)
- expect(queue.tail).toBe(3)
- expect(queue.max).toBe(3)
- expect(queue.items).toStrictEqual({ 0: 1, 1: 2, 2: 3 })
+ expect(queue.offset).toBe(0)
+ expect(queue.maxSize).toBe(3)
+ expect(queue.items).toStrictEqual([1, 2, 3])
})
it('Verify dequeue() behavior', () => {
let rtItem = queue.dequeue()
expect(queue.size).toBe(2)
expect(rtItem).toBe(1)
- expect(queue.head).toBe(1)
- expect(queue.tail).toBe(3)
- expect(queue.max).toBe(3)
- expect(queue.items).toStrictEqual({ 1: 2, 2: 3 })
+ expect(queue.offset).toBe(1)
+ expect(queue.maxSize).toBe(3)
+ expect(queue.items).toStrictEqual([1, 2, 3])
rtItem = queue.dequeue()
expect(queue.size).toBe(1)
expect(rtItem).toBe(2)
- expect(queue.head).toBe(2)
- expect(queue.tail).toBe(3)
- expect(queue.max).toBe(3)
- expect(queue.items).toStrictEqual({ 2: 3 })
+ expect(queue.offset).toBe(0)
+ expect(queue.maxSize).toBe(3)
+ expect(queue.items).toStrictEqual([3])
rtItem = queue.dequeue()
expect(queue.size).toBe(0)
expect(rtItem).toBe(3)
- expect(queue.head).toBe(0)
- expect(queue.tail).toBe(0)
- expect(queue.max).toBe(3)
- expect(queue.items).toStrictEqual({})
+ expect(queue.offset).toBe(0)
+ expect(queue.maxSize).toBe(3)
+ expect(queue.items).toStrictEqual([])
})
})