Queue implementation using two Stacks (#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>
This commit is contained in:
amirsoroush 2023-04-08 14:41:08 +03:00 committed by GitHub
parent 179298e3a2
commit 5cb0a000c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,115 @@
"""Queue implementation using two stacks"""
from collections.abc import Iterable
from typing import Generic, TypeVar
_T = TypeVar("_T")
class QueueByTwoStacks(Generic[_T]):
def __init__(self, iterable: Iterable[_T] | None = None) -> None:
"""
>>> QueueByTwoStacks()
Queue(())
>>> QueueByTwoStacks([10, 20, 30])
Queue((10, 20, 30))
>>> QueueByTwoStacks((i**2 for i in range(1, 4)))
Queue((1, 4, 9))
"""
self._stack1: list[_T] = list(iterable or [])
self._stack2: list[_T] = []
def __len__(self) -> int:
"""
>>> len(QueueByTwoStacks())
0
>>> from string import ascii_lowercase
>>> len(QueueByTwoStacks(ascii_lowercase))
26
>>> queue = QueueByTwoStacks()
>>> for i in range(1, 11):
... queue.put(i)
...
>>> len(queue)
10
>>> for i in range(2):
... queue.get()
1
2
>>> len(queue)
8
"""
return len(self._stack1) + len(self._stack2)
def __repr__(self) -> str:
"""
>>> queue = QueueByTwoStacks()
>>> queue
Queue(())
>>> str(queue)
'Queue(())'
>>> queue.put(10)
>>> queue
Queue((10,))
>>> queue.put(20)
>>> queue.put(30)
>>> queue
Queue((10, 20, 30))
"""
return f"Queue({tuple(self._stack2[::-1] + self._stack1)})"
def put(self, item: _T) -> None:
"""
Put `item` into the Queue
>>> queue = QueueByTwoStacks()
>>> queue.put(10)
>>> queue.put(20)
>>> len(queue)
2
>>> queue
Queue((10, 20))
"""
self._stack1.append(item)
def get(self) -> _T:
"""
Get `item` from the Queue
>>> queue = QueueByTwoStacks((10, 20, 30))
>>> queue.get()
10
>>> queue.put(40)
>>> queue.get()
20
>>> queue.get()
30
>>> len(queue)
1
>>> queue.get()
40
>>> queue.get()
Traceback (most recent call last):
...
IndexError: Queue is empty
"""
# To reduce number of attribute look-ups in `while` loop.
stack1_pop = self._stack1.pop
stack2_append = self._stack2.append
if not self._stack2:
while self._stack1:
stack2_append(stack1_pop())
if not self._stack2:
raise IndexError("Queue is empty")
return self._stack2.pop()
if __name__ == "__main__":
from doctest import testmod
testmod()

View File

@ -0,0 +1,137 @@
"""Queue implementation using two stacks"""
from collections.abc import Iterable
from typing import Generic, TypeVar
_T = TypeVar("_T")
class QueueByTwoStacks(Generic[_T]):
def __init__(self, iterable: Iterable[_T] | None = None) -> None:
"""
>>> queue1 = QueueByTwoStacks()
>>> str(queue1)
'Queue([])'
>>> queue2 = QueueByTwoStacks([10, 20, 30])
>>> str(queue2)
'Queue([10, 20, 30])'
>>> queue3 = QueueByTwoStacks((i**2 for i in range(1, 4)))
>>> str(queue3)
'Queue([1, 4, 9])'
"""
self._stack1: list[_T] = [] if iterable is None else list(iterable)
self._stack2: list[_T] = []
def __len__(self) -> int:
"""
>>> queue = QueueByTwoStacks()
>>> for i in range(1, 11):
... queue.put(i)
...
>>> len(queue) == 10
True
>>> for i in range(2):
... queue.get()
1
2
>>> len(queue) == 8
True
"""
return len(self._stack1) + len(self._stack2)
def __repr__(self) -> str:
"""
>>> queue = QueueByTwoStacks()
>>> queue
Queue([])
>>> str(queue)
'Queue([])'
>>> queue.put(10)
>>> queue
Queue([10])
>>> queue.put(20)
>>> queue.put(30)
>>> queue
Queue([10, 20, 30])
"""
items = self._stack2[::-1] + self._stack1
return f"Queue({items})"
def put(self, item: _T) -> None:
"""
Put `item` into the Queue
>>> queue = QueueByTwoStacks()
>>> queue.put(10)
>>> queue.put(20)
>>> len(queue) == 2
True
>>> str(queue)
'Queue([10, 20])'
"""
self._stack1.append(item)
def get(self) -> _T:
"""
Get `item` from the Queue
>>> queue = QueueByTwoStacks()
>>> for i in (10, 20, 30):
... queue.put(i)
>>> queue.get()
10
>>> queue.put(40)
>>> queue.get()
20
>>> queue.get()
30
>>> len(queue) == 1
True
>>> queue.get()
40
>>> queue.get()
Traceback (most recent call last):
...
IndexError: Queue is empty
"""
# To reduce number of attribute look-ups in `while` loop.
stack1_pop = self._stack1.pop
stack2_append = self._stack2.append
if not self._stack2:
while self._stack1:
stack2_append(stack1_pop())
if not self._stack2:
raise IndexError("Queue is empty")
return self._stack2.pop()
def size(self) -> int:
"""
Returns the length of the Queue
>>> queue = QueueByTwoStacks()
>>> queue.size()
0
>>> queue.put(10)
>>> queue.put(20)
>>> queue.size()
2
>>> queue.get()
10
>>> queue.size() == 1
True
"""
return len(self)
if __name__ == "__main__":
from doctest import testmod
testmod()