mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-27 19:38:39 +00:00
A stack implementation that tracks min/max element in constant time
This commit is contained in:
parent
d0c54acd75
commit
4c4196af9b
145
data_structures/stacks/stack_tracking_min_max.py
Normal file
145
data_structures/stacks/stack_tracking_min_max.py
Normal file
@ -0,0 +1,145 @@
|
||||
"""
|
||||
Python3 stack implementation that retrieves min/max elements of the stack in constant time
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import math
|
||||
|
||||
"""
|
||||
Data object for stack
|
||||
"""
|
||||
class StackData:
|
||||
def __init__(self, current_value: float, min_value: float, max_value: float) -> None:
|
||||
self.current_value = current_value
|
||||
self.min_value = min_value
|
||||
self.max_value = max_value
|
||||
|
||||
"""
|
||||
Main stack implementation
|
||||
"""
|
||||
class MinMaxStack:
|
||||
def __init__(self, max_stack_size: int = 10) -> None:
|
||||
self.max_size = max_stack_size
|
||||
self.stack = []
|
||||
|
||||
def push_value(self, value: float) -> bool:
|
||||
"""
|
||||
>>> test_stack = MinMaxStack(3)
|
||||
>>> test_stack.push_value(1)
|
||||
True
|
||||
>>> test_stack.push_value(2)
|
||||
True
|
||||
>>> test_stack.push_value(3)
|
||||
True
|
||||
>>> test_stack.push_value(4)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Exception: Max stack size reached. Remove elements before adding new ones or increase stack size.
|
||||
|
||||
"""
|
||||
|
||||
if len(self.stack) == self.max_size:
|
||||
raise Exception("Max stack size reached. Remove elements before adding new ones or increase stack size.")
|
||||
|
||||
if len(self.stack) == 0:
|
||||
self.stack.append(StackData(value, value, value))
|
||||
else:
|
||||
"""Store min/max values with current value"""
|
||||
|
||||
new_min = min(self.stack[-1].min_value, value)
|
||||
new_max = max(self.stack[-1].max_value, value)
|
||||
self.stack.append(StackData(value, new_min, new_max))
|
||||
|
||||
return True
|
||||
|
||||
def pop_value(self) -> float:
|
||||
"""
|
||||
>>> test_stack = MinMaxStack()
|
||||
>>> test_stack.push_value(1)
|
||||
True
|
||||
>>> test_stack.push_value(2)
|
||||
True
|
||||
>>> test_stack.pop_value()
|
||||
2
|
||||
>>> test_stack.pop_value()
|
||||
1
|
||||
>>> test_stack.pop_value()
|
||||
Stack is empty
|
||||
-inf
|
||||
"""
|
||||
|
||||
if self.stack_is_valid():
|
||||
return self.stack.pop().current_value
|
||||
|
||||
return -math.inf
|
||||
|
||||
def get_current_max(self) -> float:
|
||||
"""
|
||||
test_stack = MinMaxStack(3)
|
||||
>>> test_stack.push_value(-450.45)
|
||||
True
|
||||
>>> test_stack.push_value(450.45)
|
||||
True
|
||||
>>> test_stack.push_value(0)
|
||||
True
|
||||
>>> test_stack.get_current_max()
|
||||
450.45
|
||||
>>> test_stack.pop_value()
|
||||
0
|
||||
>>> test_stack.get_current_max()
|
||||
450.45
|
||||
>>> test_stack.pop_value()
|
||||
450.45
|
||||
>>> test_stack.get_current_max()
|
||||
-450.45
|
||||
>>> test_stack.pop_value()
|
||||
-450.45
|
||||
>>> test_stack.get_current_max()
|
||||
Stack is empty
|
||||
-inf
|
||||
"""
|
||||
if self.stack_is_valid():
|
||||
return self.stack[-1].max_value
|
||||
|
||||
return -math.inf
|
||||
|
||||
def get_current_min(self) -> float:
|
||||
"""
|
||||
>>> test_stack = MinMaxStack(3)
|
||||
>>> test_stack.push_value(123)
|
||||
True
|
||||
>>> test_stack.push_value(-123)
|
||||
True
|
||||
>>> test_stack.push_value(0)
|
||||
True
|
||||
>>> test_stack.get_current_min()
|
||||
-123
|
||||
>>> test_stack.pop_value()
|
||||
0
|
||||
>>> test_stack.get_current_min()
|
||||
-123
|
||||
>>> test_stack.pop_value()
|
||||
-123
|
||||
>>> test_stack.get_current_min()
|
||||
123
|
||||
>>> test_stack.pop_value()
|
||||
123
|
||||
>>> test_stack.get_current_min()
|
||||
Stack is empty
|
||||
-inf
|
||||
"""
|
||||
if self.stack_is_valid():
|
||||
return self.stack[-1].min_value
|
||||
|
||||
return -math.inf
|
||||
|
||||
def stack_is_valid(self) -> bool:
|
||||
if len(self.stack) == 0:
|
||||
print("Stack is empty")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from doctest import testmod
|
||||
testmod()
|
Loading…
x
Reference in New Issue
Block a user