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 name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 36.67 | 27.27 | 0.00 |
1,000,000 shift | 35.78 | 27.95 | 0.00 |
1,000,000 push | 35.96 | 27.81 | 0.00 |
1,000,000 push & pop | 39.29 | 25.45 | 0.00 |
1,000,000 push & shift | 39.46 | 25.34 | 0.00 |
1,000,000 unshift & shift | 36.93 | 27.08 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 70.01 | 14.28 | 0.01 |
1,000,000 CPT push | 14.52 | 68.86 | 0.00 |
1,000,000 push & pop | 72.74 | 13.75 | 0.01 |
1,000,000 push & shift | 74.59 | 13.41 | 0.01 |
1,000,000 unshift & shift | 72.73 | 13.75 | 0.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);
+ });
+});