From 599492a077d8369393d0a0672fe84aa5a8ee1043 Mon Sep 17 00:00:00 2001 From: zfl4wless Date: Thu, 16 Mar 2023 21:11:30 +0100 Subject: [PATCH 1/2] feat(structure): implements circular queue --- data_structures/queue/circular_queue.ts | 112 ++++++++++++++++++ .../queue/test/circular_queue.test.ts | 65 ++++++++++ 2 files changed, 177 insertions(+) create mode 100644 data_structures/queue/circular_queue.ts create mode 100644 data_structures/queue/test/circular_queue.test.ts diff --git a/data_structures/queue/circular_queue.ts b/data_structures/queue/circular_queue.ts new file mode 100644 index 00000000..782516b3 --- /dev/null +++ b/data_structures/queue/circular_queue.ts @@ -0,0 +1,112 @@ +import { Queue } from "./queue"; + +/** + * Circular Queue implementation using array. + * + * @template T The type of the elements in the queue. + * @implements {Queue} + * @param {T[]} queue The array that holds the elements of the queue. + * @param {number} frontIndex The index of the front element of the queue. + * @param {number} rearIndex The index of the rear element of the queue. + * @param {number} size The size of the queue. + */ +export class CircularQueue implements Queue { + private queue: T[]; + private frontIndex: number; + private rearIndex: number; + private size: number; + + constructor(size: number) { + this.queue = new Array(size); + this.frontIndex = -1; + this.rearIndex = -1; + this.size = size; + } + + /** + * Adds an item to the queue. + * + * @param item The item being added to the queue. + */ + enqueue(item: T): void { + if ( + (this.frontIndex == 0 && this.rearIndex == this.size - 1) || + this.rearIndex == (this.frontIndex - 1) % (this.size - 1) + ) { + throw new Error("Queue is full"); + } else if (this.frontIndex == -1) { + this.frontIndex = 0; + this.rearIndex = 0; + this.queue[this.rearIndex] = item; + } else if (this.rearIndex == this.size - 1 && this.frontIndex != 0) { + this.rearIndex = 0; + this.queue[this.rearIndex] = item; + } else { + this.rearIndex++; + this.queue[this.rearIndex] = item; + } + } + + /** + * Removes an item from the queue and returns it. + * + * @throws Queue Underflow if the queue is empty. + * @returns The item that was removed from the queue. + */ + dequeue(): T | undefined { + if (this.frontIndex == -1) { + throw new Error("Queue is empty"); + } + + const item = this.queue[this.frontIndex]; + if (this.frontIndex == this.rearIndex) { + this.frontIndex = -1; + this.rearIndex = -1; + } else if (this.frontIndex == this.size - 1) { + this.frontIndex = 0; + } else { + this.frontIndex++; + } + + return item; + } + + /** + * Returns the item at the front of the queue. + * + * @returns The item at the front of the queue or null if the queue is empty. + */ + peek(): T | null | undefined { + if (this.frontIndex == -1) { + return null; + } + + return this.queue[this.frontIndex]; + } + + /** + * Checks if the queue is empty. + * + * @returns {boolean} Whether the queue is empty or not. + */ + isEmpty(): boolean { + return this.frontIndex == -1; + } + + /** + * Returns the number of items in the queue. + * + * @returns {number} The number of items in the queue. + */ + length(): number { + if (this.frontIndex == -1) { + return 0; + } + + if (this.rearIndex >= this.frontIndex) { + return this.rearIndex - this.frontIndex + 1; + } + + return this.size - (this.frontIndex - this.rearIndex - 1); + } +} diff --git a/data_structures/queue/test/circular_queue.test.ts b/data_structures/queue/test/circular_queue.test.ts new file mode 100644 index 00000000..042e5d81 --- /dev/null +++ b/data_structures/queue/test/circular_queue.test.ts @@ -0,0 +1,65 @@ +import { CircularQueue } from "../circular_queue"; + +describe("Circular Queue", () => { + let queue: CircularQueue; + + beforeEach(() => { + queue = new CircularQueue(5); + }); + + it("should enqueue an element", () => { + queue.enqueue(1); + + expect(queue.peek()).toBe(1); + }); + + it("should throw an error on enqueue when queue is full", () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + queue.enqueue(4); + queue.enqueue(5); + + expect(() => queue.enqueue(6)).toThrowError("Queue is full"); + }); + + it("should dequeue an element", () => { + queue.enqueue(1); + queue.enqueue(2); + + expect(queue.dequeue()).toBe(1); + }); + + it("should throw an error on dequeue when queue is empty", () => { + expect(() => queue.dequeue()).toThrowError("Queue is empty"); + }); + + it("should peek an element", () => { + queue.enqueue(1); + queue.enqueue(2); + + expect(queue.peek()).toBe(1); + }); + + it("should return null on peek when queue is empty", () => { + expect(queue.peek()).toBeNull(); + }); + + it("should return true on isEmpty when queue is empty", () => { + expect(queue.isEmpty()).toBeTruthy(); + }); + + it("should return false on isEmpty when queue is not empty", () => { + queue.enqueue(1); + + expect(queue.isEmpty()).toBeFalsy(); + }); + + it("should return the correct length", () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + expect(queue.length()).toBe(3); + }); +}); From 927d2e067bafc3b0db1306657c262007db65ba15 Mon Sep 17 00:00:00 2001 From: zfl4wless Date: Fri, 17 Mar 2023 22:20:24 +0100 Subject: [PATCH 2/2] feat: circular queue no longer implements queue interface --- data_structures/queue/circular_queue.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/data_structures/queue/circular_queue.ts b/data_structures/queue/circular_queue.ts index 782516b3..ce42e059 100644 --- a/data_structures/queue/circular_queue.ts +++ b/data_structures/queue/circular_queue.ts @@ -1,16 +1,13 @@ -import { Queue } from "./queue"; - /** * Circular Queue implementation using array. * * @template T The type of the elements in the queue. - * @implements {Queue} * @param {T[]} queue The array that holds the elements of the queue. * @param {number} frontIndex The index of the front element of the queue. * @param {number} rearIndex The index of the rear element of the queue. * @param {number} size The size of the queue. */ -export class CircularQueue implements Queue { +export class CircularQueue { private queue: T[]; private frontIndex: number; private rearIndex: number;