Skip to content

Commit da6b1a9

Browse files
authored
feat: add queue implementation using two stacks (#89)
1 parent 124890c commit da6b1a9

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

data_structures/stack_queue.ts

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* A Stack Based Queue Implementation.
3+
* The Queue data structure which follows the FIFO (First in First Out) rule.
4+
* The dequeue operation in a normal stack based queue would be o(n), as the entire has to be shifted
5+
* With the help of two stacks, the time complexity of this can be brought down to amortized-O(1).
6+
* Here, one stack acts as an Enqueue stack where elements are added.
7+
* The other stack acts as a dequeue stack which helps in dequeuing the elements
8+
*/
9+
10+
import { Queue } from './queue';
11+
import { Stack } from './stack';
12+
13+
export class StackQueue<T> implements Queue<T>{
14+
15+
private enqueueStack: Stack<T> = new Stack<T>();
16+
private dequeueStack: Stack<T> = new Stack<T>();
17+
18+
/**
19+
* Returns the length of the Queue
20+
*
21+
* @returns {number} the length of the Queue
22+
*/
23+
length(): number {
24+
return this.enqueueStack.length() + this.dequeueStack.length();
25+
}
26+
27+
/**
28+
* Checks if the queue is empty.
29+
*
30+
* @returns {boolean} Whether the queue is empty or not.
31+
*/
32+
isEmpty(): boolean {
33+
return this.enqueueStack.isEmpty() && this.dequeueStack.isEmpty();
34+
}
35+
36+
/**
37+
* Adds an item to the queue.
38+
* We always add a new item to the enqueueStack.
39+
* @param item The item being added to the queue.
40+
*/
41+
enqueue(item: T): void {
42+
this.enqueueStack.push(item);
43+
}
44+
45+
/**
46+
* Shifts the elements from the enqueueStack to the dequeueStack
47+
* In the worst case, all the elements from the enqueue stack needs to shifted, which needs O(n) time.
48+
* However, after the shift, elements can de dequeued at O(1).
49+
* This helps in dequeuing the elements in amortized O(1) time.
50+
*/
51+
private shift(): void {
52+
while (!this.enqueueStack.isEmpty()) {
53+
const enqueueStackTop = this.enqueueStack.pop();
54+
this.dequeueStack.push(enqueueStackTop);
55+
}
56+
}
57+
58+
/**
59+
* Removes an item from the queue and returns it.
60+
*
61+
* @throws Queue Underflow if the queue is empty.
62+
* @returns The item that was removed from the queue.
63+
*/
64+
dequeue(): T {
65+
if (this.isEmpty()) {
66+
throw new Error("Queue Underflow");
67+
}
68+
69+
if (this.dequeueStack.isEmpty()) {
70+
this.shift();
71+
}
72+
73+
return this.dequeueStack.pop();
74+
}
75+
76+
/**
77+
* Returns the item at the front of the queue.
78+
*
79+
* @returns The item at the front of the queue or null if the queue is empty.
80+
*/
81+
peek(): T | null {
82+
if (this.isEmpty()) {
83+
return null;
84+
}
85+
86+
if (this.dequeueStack.isEmpty()) {
87+
this.shift();
88+
}
89+
90+
return this.dequeueStack.top();
91+
}
92+
}
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { testQueue } from './queue';
2+
import { StackQueue } from '../stack_queue';
3+
4+
describe("Stack Based Queue", () => testQueue(StackQueue));

0 commit comments

Comments
 (0)