Skip to content

Commit eee9556

Browse files
amirsoroushcclauss
authored andcommitted
Queue implementation using two Stacks (TheAlgorithms#8617)
* Queue implementation using two Stacks * fix typo in queue/queue_on_two_stacks.py * add 'iterable' to queue_on_two_stacks initializer * make queue_on_two_stacks.py generic class * fix ruff-UP007 in queue_on_two_stacks.py * enhance readability in queue_on_two_stacks.py * Create queue_by_two_stacks.py --------- Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent e892665 commit eee9556

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""Queue implementation using two stacks"""
2+
3+
from collections.abc import Iterable
4+
from typing import Generic, TypeVar
5+
6+
_T = TypeVar("_T")
7+
8+
9+
class QueueByTwoStacks(Generic[_T]):
10+
def __init__(self, iterable: Iterable[_T] | None = None) -> None:
11+
"""
12+
>>> QueueByTwoStacks()
13+
Queue(())
14+
>>> QueueByTwoStacks([10, 20, 30])
15+
Queue((10, 20, 30))
16+
>>> QueueByTwoStacks((i**2 for i in range(1, 4)))
17+
Queue((1, 4, 9))
18+
"""
19+
self._stack1: list[_T] = list(iterable or [])
20+
self._stack2: list[_T] = []
21+
22+
def __len__(self) -> int:
23+
"""
24+
>>> len(QueueByTwoStacks())
25+
0
26+
>>> from string import ascii_lowercase
27+
>>> len(QueueByTwoStacks(ascii_lowercase))
28+
26
29+
>>> queue = QueueByTwoStacks()
30+
>>> for i in range(1, 11):
31+
... queue.put(i)
32+
...
33+
>>> len(queue)
34+
10
35+
>>> for i in range(2):
36+
... queue.get()
37+
1
38+
2
39+
>>> len(queue)
40+
8
41+
"""
42+
43+
return len(self._stack1) + len(self._stack2)
44+
45+
def __repr__(self) -> str:
46+
"""
47+
>>> queue = QueueByTwoStacks()
48+
>>> queue
49+
Queue(())
50+
>>> str(queue)
51+
'Queue(())'
52+
>>> queue.put(10)
53+
>>> queue
54+
Queue((10,))
55+
>>> queue.put(20)
56+
>>> queue.put(30)
57+
>>> queue
58+
Queue((10, 20, 30))
59+
"""
60+
return f"Queue({tuple(self._stack2[::-1] + self._stack1)})"
61+
62+
def put(self, item: _T) -> None:
63+
"""
64+
Put `item` into the Queue
65+
66+
>>> queue = QueueByTwoStacks()
67+
>>> queue.put(10)
68+
>>> queue.put(20)
69+
>>> len(queue)
70+
2
71+
>>> queue
72+
Queue((10, 20))
73+
"""
74+
75+
self._stack1.append(item)
76+
77+
def get(self) -> _T:
78+
"""
79+
Get `item` from the Queue
80+
81+
>>> queue = QueueByTwoStacks((10, 20, 30))
82+
>>> queue.get()
83+
10
84+
>>> queue.put(40)
85+
>>> queue.get()
86+
20
87+
>>> queue.get()
88+
30
89+
>>> len(queue)
90+
1
91+
>>> queue.get()
92+
40
93+
>>> queue.get()
94+
Traceback (most recent call last):
95+
...
96+
IndexError: Queue is empty
97+
"""
98+
99+
# To reduce number of attribute look-ups in `while` loop.
100+
stack1_pop = self._stack1.pop
101+
stack2_append = self._stack2.append
102+
103+
if not self._stack2:
104+
while self._stack1:
105+
stack2_append(stack1_pop())
106+
107+
if not self._stack2:
108+
raise IndexError("Queue is empty")
109+
return self._stack2.pop()
110+
111+
112+
if __name__ == "__main__":
113+
from doctest import testmod
114+
115+
testmod()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
"""Queue implementation using two stacks"""
2+
3+
from collections.abc import Iterable
4+
from typing import Generic, TypeVar
5+
6+
_T = TypeVar("_T")
7+
8+
9+
class QueueByTwoStacks(Generic[_T]):
10+
def __init__(self, iterable: Iterable[_T] | None = None) -> None:
11+
"""
12+
>>> queue1 = QueueByTwoStacks()
13+
>>> str(queue1)
14+
'Queue([])'
15+
>>> queue2 = QueueByTwoStacks([10, 20, 30])
16+
>>> str(queue2)
17+
'Queue([10, 20, 30])'
18+
>>> queue3 = QueueByTwoStacks((i**2 for i in range(1, 4)))
19+
>>> str(queue3)
20+
'Queue([1, 4, 9])'
21+
"""
22+
23+
self._stack1: list[_T] = [] if iterable is None else list(iterable)
24+
self._stack2: list[_T] = []
25+
26+
def __len__(self) -> int:
27+
"""
28+
>>> queue = QueueByTwoStacks()
29+
>>> for i in range(1, 11):
30+
... queue.put(i)
31+
...
32+
>>> len(queue) == 10
33+
True
34+
>>> for i in range(2):
35+
... queue.get()
36+
1
37+
2
38+
>>> len(queue) == 8
39+
True
40+
"""
41+
42+
return len(self._stack1) + len(self._stack2)
43+
44+
def __repr__(self) -> str:
45+
"""
46+
>>> queue = QueueByTwoStacks()
47+
>>> queue
48+
Queue([])
49+
>>> str(queue)
50+
'Queue([])'
51+
>>> queue.put(10)
52+
>>> queue
53+
Queue([10])
54+
>>> queue.put(20)
55+
>>> queue.put(30)
56+
>>> queue
57+
Queue([10, 20, 30])
58+
"""
59+
60+
items = self._stack2[::-1] + self._stack1
61+
return f"Queue({items})"
62+
63+
def put(self, item: _T) -> None:
64+
"""
65+
Put `item` into the Queue
66+
67+
>>> queue = QueueByTwoStacks()
68+
>>> queue.put(10)
69+
>>> queue.put(20)
70+
>>> len(queue) == 2
71+
True
72+
>>> str(queue)
73+
'Queue([10, 20])'
74+
"""
75+
76+
self._stack1.append(item)
77+
78+
def get(self) -> _T:
79+
"""
80+
Get `item` from the Queue
81+
82+
>>> queue = QueueByTwoStacks()
83+
>>> for i in (10, 20, 30):
84+
... queue.put(i)
85+
>>> queue.get()
86+
10
87+
>>> queue.put(40)
88+
>>> queue.get()
89+
20
90+
>>> queue.get()
91+
30
92+
>>> len(queue) == 1
93+
True
94+
>>> queue.get()
95+
40
96+
>>> queue.get()
97+
Traceback (most recent call last):
98+
...
99+
IndexError: Queue is empty
100+
"""
101+
102+
# To reduce number of attribute look-ups in `while` loop.
103+
stack1_pop = self._stack1.pop
104+
stack2_append = self._stack2.append
105+
106+
if not self._stack2:
107+
while self._stack1:
108+
stack2_append(stack1_pop())
109+
110+
if not self._stack2:
111+
raise IndexError("Queue is empty")
112+
return self._stack2.pop()
113+
114+
def size(self) -> int:
115+
"""
116+
Returns the length of the Queue
117+
118+
>>> queue = QueueByTwoStacks()
119+
>>> queue.size()
120+
0
121+
>>> queue.put(10)
122+
>>> queue.put(20)
123+
>>> queue.size()
124+
2
125+
>>> queue.get()
126+
10
127+
>>> queue.size() == 1
128+
True
129+
"""
130+
131+
return len(self)
132+
133+
134+
if __name__ == "__main__":
135+
from doctest import testmod
136+
137+
testmod()

0 commit comments

Comments
 (0)