diff --git a/README.md b/README.md index 32b1d16..55134de 100644 --- a/README.md +++ b/README.md @@ -808,7 +808,7 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.key) // ['A', 'B', ' [//]: # (No deletion!!! Start of Replace Section)
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push36.6727.270.00
1,000,000 shift35.7827.950.00
1,000,000 push35.9627.810.00
1,000,000 push & pop39.2925.450.00
1,000,000 push & shift39.4625.340.00
1,000,000 unshift & shift36.9327.080.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push70.0114.280.01
1,000,000 CPT push14.5268.860.00
1,000,000 push & pop72.7413.750.01
1,000,000 push & shift74.5913.410.01
1,000,000 unshift & shift72.7313.750.01
[//]: # (No deletion!!! End of Replace Section) diff --git a/src/data-structures/queue/deque.ts b/src/data-structures/queue/deque.ts index 97050af..83d08a8 100644 --- a/src/data-structures/queue/deque.ts +++ b/src/data-structures/queue/deque.ts @@ -308,22 +308,19 @@ export class Deque { return false; } - // If inserted at the head if (index === 0) { this.unshift(element); return true; } - //If inserted at the end if (index === this.size) { this.push(element); return true; } - // Intermediate insertion requires processing of arrays this._ensureCapacityForInsert(); - const actualIndex = this.headOffset + index; - for (let i = this.tailOffset; i > actualIndex; i--) { + const actualIndex = this._headOffset + index; + for (let i = this._tailOffset; i > actualIndex; i--) { this._elements[i] = this._elements[i - 1]; } this._elements[actualIndex] = element; @@ -352,17 +349,17 @@ export class Deque { return undefined; } - const actualIndex = this.headOffset + index; + const actualIndex = this._headOffset + index; const removedElement = this._elements[actualIndex]; - - for (let i = actualIndex; i < this.tailOffset - 1; i++) { + for (let i = actualIndex; i < this._tailOffset - 1; i++) { this._elements[i] = this._elements[i + 1]; } - this._tailOffset--; + this._elements[this._tailOffset] = undefined as unknown as E; // Clear reference to the last element return removedElement; } + /** * Time Complexity: O(n) - May need to scan the entire deque. * Space Complexity: O(1) - No extra space required. @@ -607,16 +604,17 @@ export class Deque { protected _resize() { const newCapacity = this.capacity * 2; const newElements = new Array(newCapacity); - const newHeadOffset = Math.floor((newCapacity - this.size) / 2); + const size = this.size; + const newHeadOffset = Math.floor((newCapacity - size) / 2); - for (let i = 0; i < this.size; i++) { - newElements[newHeadOffset + i] = this._elements[this.headOffset + i]; + for (let i = 0; i < size; i++) { + newElements[newHeadOffset + i] = this._elements[this._headOffset + i]; } this._elements = newElements; this._capacity = newCapacity; this._headOffset = newHeadOffset; - this._tailOffset = newHeadOffset + this.size; + this._tailOffset = newHeadOffset + size; } /** diff --git a/test/performance/data-structures/queue/deque.test.ts b/test/performance/data-structures/queue/deque.test.ts index 0019241..d8677bd 100644 --- a/test/performance/data-structures/queue/deque.test.ts +++ b/test/performance/data-structures/queue/deque.test.ts @@ -9,49 +9,33 @@ const { LINEAR } = magnitude; suite.add(`${LINEAR.toLocaleString()} push`, () => { const deque = new Deque(); - for (let i = 0; i < LINEAR; i++) { - deque.push(i); - } + for (let i = 0; i < LINEAR; i++) deque.push(i); }); + if (isCompetitor) { suite.add(`${LINEAR.toLocaleString()} CPT push`, () => { - const deque = new CDeque(); - for (let i = 0; i < LINEAR; i++) { - deque.pushBack(i); - } + const _deque = new CDeque(); + for (let i = 0; i < LINEAR; i++) _deque.pushBack(i); }); } -suite.add(`${LINEAR.toLocaleString()} shift`, () => { - const deque = new Deque(); - for (let i = 0; i < LINEAR; i++) { - deque.push(i); - deque.shift(); - } -}); -suite.add(`${LINEAR.toLocaleString()} push`, () => { - const list = new Deque(); - for (let i = 0; i < LINEAR; i++) { - list.push(i); - } -}); suite.add(`${LINEAR.toLocaleString()} push & pop`, () => { - const list = new Deque(); + const _deque = new Deque(); - for (let i = 0; i < LINEAR; i++) list.push(i); - for (let i = 0; i < LINEAR; i++) list.pop(); + for (let i = 0; i < LINEAR; i++) _deque.push(i); + for (let i = 0; i < LINEAR; i++) _deque.pop(); }); suite.add(`${LINEAR.toLocaleString()} push & shift`, () => { - const list = new Deque(); + const _deque = new Deque(); - for (let i = 0; i < LINEAR; i++) list.push(i); - for (let i = 0; i < LINEAR; i++) list.shift(); + for (let i = 0; i < LINEAR; i++) _deque.push(i); + for (let i = 0; i < LINEAR; i++) _deque.shift(); }); suite.add(`${LINEAR.toLocaleString()} unshift & shift`, () => { - const list = new Deque(); + const _deque = new Deque(); - for (let i = 0; i < LINEAR; i++) list.unshift(i); - for (let i = 0; i < LINEAR; i++) list.shift(); + for (let i = 0; i < LINEAR; i++) _deque.unshift(i); + for (let i = 0; i < LINEAR; i++) _deque.shift(); }); diff --git a/test/unit/data-structures/queue/deque.test.ts b/test/unit/data-structures/queue/deque.test.ts index d4e7fef..b1cfb8d 100644 --- a/test/unit/data-structures/queue/deque.test.ts +++ b/test/unit/data-structures/queue/deque.test.ts @@ -272,3 +272,149 @@ describe('ObjectDeque', () => { expect(deque.getLast()).toBe(3); }); }); + + +describe('Deque', () => { + let deque: Deque; + + beforeEach(() => { + deque = new Deque(); + }); + + test('initializes with default capacity', () => { + expect(deque.capacity).toBe(10); + }); + + test('initializes with given capacity', () => { + const customDeque = new Deque(20); + expect(customDeque.capacity).toBe(20); + }); + + test('is initially empty', () => { + expect(deque.isEmpty()).toBe(true); + }); + + test('pushes and pops elements', () => { + deque.push(1); + deque.push(2); + expect(deque.pop()).toBe(2); + expect(deque.pop()).toBe(1); + expect(deque.pop()).toBeUndefined(); + }); + + test('unshifts and shifts elements', () => { + deque.unshift(1); + deque.unshift(2); + expect(deque.shift()).toBe(2); + expect(deque.shift()).toBe(1); + expect(deque.shift()).toBeUndefined(); + }); + + test('correctly reports size', () => { + expect(deque.size).toBe(0); + deque.push(1); + deque.push(2); + expect(deque.size).toBe(2); + }); + + test('gets first and last elements', () => { + deque.push(1); + deque.push(2); + deque.push(3); + expect(deque.getFirst()).toBe(1); + expect(deque.getLast()).toBe(3); + }); + + test('handles resizing automatically', () => { + for (let i = 0; i < 12; i++) { + deque.push(i); + } + expect(deque.size).toBe(12); + expect(deque.capacity).toBeGreaterThan(10); + }); + + test('converts to array', () => { + deque.push(1); + deque.push(2); + deque.push(3); + expect(deque.toArray()).toEqual([1, 2, 3]); + }); + + test('clears the deque', () => { + deque.push(1); + deque.push(2); + deque.clear(); + expect(deque.isEmpty()).toBe(true); + }); + + test('inserts and deletes at specific index', () => { + deque.push(1); + deque.push(3); + deque.insertAt(1, 2); + expect(deque.toArray()).toEqual([1, 2, 3]); + expect(deque.deleteAt(1)).toBe(2); + expect(deque.toArray()).toEqual([1, 3]); + }); + + test('finds elements with a callback', () => { + deque.push(1); + deque.push(2); + deque.push(3); + expect(deque.find(el => el > 1)).toBe(2); + }); + + test('performs forEach operation', () => { + deque.push(1); + deque.push(2); + let sum = 0; + deque.forEach(el => { sum += el; }); + expect(sum).toBe(3); + }); + + test('maps to a new deque', () => { + deque.push(1); + deque.push(2); + const newDeque = deque.map(el => el * el); + expect(newDeque.toArray()).toEqual([1, 4]); + }); + + test('filters elements', () => { + deque.push(1); + deque.push(2); + deque.push(3); + const newDeque = deque.filter(el => el % 2 === 0); + expect(newDeque.toArray()).toEqual([2]); + }); + + test('reduces elements', () => { + deque.push(1); + deque.push(2); + deque.push(3); + const sum = deque.reduce((acc, el) => acc + el, 0); + expect(sum).toBe(6); + }); + + test('reverses elements', () => { + deque.push(1); + deque.push(2); + deque.push(3); + deque.reverse(); + expect(deque.toArray()).toEqual([3, 2, 1]); + }); + + test('gets element at a specific index', () => { + deque.push(1); + deque.push(2); + deque.push(3); + expect(deque.getAt(1)).toBe(2); + expect(deque.getAt(5)).toBeUndefined(); + }); + + test('finds the index of an element', () => { + deque.push(1); + deque.push(2); + deque.push(3); + expect(deque.indexOf(2)).toBe(1); + expect(deque.indexOf(4)).toBe(-1); + }); +});