Module dsa.heap
Module containing heap (max heap), min heap and priority queue classes.
Expand source code
""" Module containing heap (max heap), min heap and priority queue classes. """
class Heap:
"""
A max heap implementation.
"""
def __init__(self):
self._array = []
@classmethod
def from_list(cls, mylist: list):
hp = cls()
for e in mylist:
hp.insert(e)
return hp
def to_list(self) -> list:
return self._array
def root(self):
"""
Get the root value.
Returns:
The root node's value. None if count is 0.
"""
if self.count() == 0:
return None
return self._array[0]
def peek(self):
"""
Get the max value of the max heap.
Returns:
The maximum value of the max heap.
"""
return self.root()
def last(self):
"""
Get the last node of the max heap.
Returns:
The last node's value.
None if count is 0.
"""
if self.count() == 0:
return None
return self._array[-1]
def left_index(self, index: int) -> int:
"""
Get the index of the left child.
Args:
index (int): The index of the node.
Returns:
Return the index of the left child.
"""
return (index * 2) + 1
def right_index(self, index: int) -> int:
"""
Get the index of the right child.
Args:
index (int): The index of the node.
Returns:
Return the index of the right child.
"""
return (index * 2) + 2
def parent_index(self, index: int) -> int:
"""
Get the index of the parent node.
Args:
index (int): The index of the node.
Returns:
Return the index of the parent child.
"""
return (index - 1) // 2
def has_left(self, index: int) -> bool:
"""
Check if current node has an left child.
Args:
index (int): The index of the node.
Returns:
Boolean on whether a node has a left child node.
"""
return self.left_index(index) < self.count()
def has_right(self, index: int) -> bool:
"""
Check if current node has an right child.
Args:
index (int): The index of the node.
Returns:
Boolean on whether a node has a right child node.
"""
return self.right_index(index) < self.count()
def has_parent(self, index: int) -> bool:
"""
Check if a node has a parent node.
Args:
index (int): The index of the node.
Returns:
Boolean on whether a node has a parent node.
"""
return self.parent_index(index) >= 0
def insert(self, value):
"""
Insert a value into the heap.
Args:
value: The value to insert.
"""
self._array.append(value)
start_index = self.count() - 1
self.heapify_up(start_index)
def heapify_up(self, index: int):
"""
Perform heapify up starting at a given index.
Args:
index (int): The starting index.
"""
parent_index = self.parent_index(index)
while self.has_parent(index) and self._array[index] > self._array[parent_index]:
self._array[index], self._array[parent_index] = self._array[parent_index], self._array[index]
index = parent_index
parent_index = self.parent_index(index)
def pop(self):
"""
Return the value of the root node (max value) and remove it from the heap.
Returns:
Return the value from the root node.
"""
root_value = self.root()
# start at root node
start_index = 0
if self.count() == 0:
raise Exception("Heap is empty")
if self.count() == 1:
self._array.pop()
else:
self._array[start_index] = self._array.pop()
self.heapify_down(start_index)
return root_value
def heapify_down(self, index: int):
"""
Perform heapify down starting at a given index.
Args:
index (int): The starting index.
"""
while self.has_left(index):
higher_index = self.left_index(index)
right_index = self.right_index(index)
if self.has_right(index) and self._array[right_index] > self._array[higher_index]:
higher_index = right_index
if self._array[index] > self._array[higher_index]:
break
else:
self._array[index], self._array[higher_index] = self._array[higher_index], self._array[index]
index = higher_index
def enumerate(self):
"""
Return the enumeration of a heap.
Returns:
Enumeration of a heap.
"""
return enumerate(self._array)
def count(self) -> int:
"""
Return the number of items in the heap.
Returns:
The number of items in the heap.
"""
return len(self._array)
def is_empty(self) -> bool:
"""
Check if a heap has any items.
Returns:
True if heap has no items.
False if heap has more than 0 items.
"""
return self.count() == 0
def print(self):
"""
Print the contents of a heap.
"""
node_count = 1
for i in range(self.count()):
if i + 1 >= node_count:
print()
node_count *= 2
print(self._array[i], end=" ")
def __repr__(self):
"""
Return string representation of a heap in order of priority.
"""
temp_array = self._array[:]
result = []
while not self.is_empty():
result.append(str(self.pop()))
self._array = temp_array
return "[" + " ".join(result) + "]"
def __len__(self):
"""
Get the number of items in the priority queue.
Returns:
Number of items in the priority queue
"""
return self.count()
class MinHeap(Heap):
def heapify_up(self, index: int):
"""
Perform heapify up starting at a given index.
Args:
index (int): The starting index.
"""
parent_index = self.parent_index(index)
while self.has_parent(index) and self._array[index] < self._array[parent_index]:
self._array[index], self._array[parent_index] = self._array[parent_index], self._array[index]
index = parent_index
parent_index = self.parent_index(index)
def heapify_down(self, index: int):
"""
Perform heapify down starting at a given index.
Args:
index (int): The starting index.
"""
while self.has_left(index):
higher_index = self.left_index(index)
right_index = self.right_index(index)
if self.has_right(index) and self._array[right_index] < self._array[higher_index]:
higher_index = right_index
if self._array[index] < self._array[higher_index]:
break
else:
self._array[index], self._array[higher_index] = self._array[higher_index], self._array[index]
index = higher_index
class PriorityQueue(MinHeap):
"""
A priority queue implementation in Python.
"""
def push(self, priority: int, item):
"""
Insert an item with a priority into the priority queue.
Args:
priority (int): Priority of item.
item: The item to insert.
"""
super().insert((priority, item))
def pop(self):
"""
Return and remove the highest priority value in the heap.
Returns:
Return The highest priority value in the heap.
"""
priority, item = super().pop()
return item
def pop_pair(self) -> tuple:
"""
Return and remove the highest priority value pair in the heap.
Returns:
Return the highest priority, value pair (tuple) in the heap.
"""
return super().pop()
def peek(self):
"""
Return the highest priority value in the heap.
Returns:
Return The highest priority value in the heap.
"""
priority, item = super().peek()
return item
def peek_pair(self) -> tuple:
"""
Return the highest priority value pair in the heap.
Returns:
Return the highest priority, value pair (tuple) in the heap.
"""
return super().peek()
def to_string_with_priority(self):
"""
Return string representation of a heap in order of priority.
"""
temp_array = self._array[:]
result = []
while not self.is_empty():
result.append(str(self.pop_pair()))
self._array = temp_array
return "[" + " ".join(result) + "]"
Classes
class Heap
-
A max heap implementation.
Expand source code
class Heap: """ A max heap implementation. """ def __init__(self): self._array = [] @classmethod def from_list(cls, mylist: list): hp = cls() for e in mylist: hp.insert(e) return hp def to_list(self) -> list: return self._array def root(self): """ Get the root value. Returns: The root node's value. None if count is 0. """ if self.count() == 0: return None return self._array[0] def peek(self): """ Get the max value of the max heap. Returns: The maximum value of the max heap. """ return self.root() def last(self): """ Get the last node of the max heap. Returns: The last node's value. None if count is 0. """ if self.count() == 0: return None return self._array[-1] def left_index(self, index: int) -> int: """ Get the index of the left child. Args: index (int): The index of the node. Returns: Return the index of the left child. """ return (index * 2) + 1 def right_index(self, index: int) -> int: """ Get the index of the right child. Args: index (int): The index of the node. Returns: Return the index of the right child. """ return (index * 2) + 2 def parent_index(self, index: int) -> int: """ Get the index of the parent node. Args: index (int): The index of the node. Returns: Return the index of the parent child. """ return (index - 1) // 2 def has_left(self, index: int) -> bool: """ Check if current node has an left child. Args: index (int): The index of the node. Returns: Boolean on whether a node has a left child node. """ return self.left_index(index) < self.count() def has_right(self, index: int) -> bool: """ Check if current node has an right child. Args: index (int): The index of the node. Returns: Boolean on whether a node has a right child node. """ return self.right_index(index) < self.count() def has_parent(self, index: int) -> bool: """ Check if a node has a parent node. Args: index (int): The index of the node. Returns: Boolean on whether a node has a parent node. """ return self.parent_index(index) >= 0 def insert(self, value): """ Insert a value into the heap. Args: value: The value to insert. """ self._array.append(value) start_index = self.count() - 1 self.heapify_up(start_index) def heapify_up(self, index: int): """ Perform heapify up starting at a given index. Args: index (int): The starting index. """ parent_index = self.parent_index(index) while self.has_parent(index) and self._array[index] > self._array[parent_index]: self._array[index], self._array[parent_index] = self._array[parent_index], self._array[index] index = parent_index parent_index = self.parent_index(index) def pop(self): """ Return the value of the root node (max value) and remove it from the heap. Returns: Return the value from the root node. """ root_value = self.root() # start at root node start_index = 0 if self.count() == 0: raise Exception("Heap is empty") if self.count() == 1: self._array.pop() else: self._array[start_index] = self._array.pop() self.heapify_down(start_index) return root_value def heapify_down(self, index: int): """ Perform heapify down starting at a given index. Args: index (int): The starting index. """ while self.has_left(index): higher_index = self.left_index(index) right_index = self.right_index(index) if self.has_right(index) and self._array[right_index] > self._array[higher_index]: higher_index = right_index if self._array[index] > self._array[higher_index]: break else: self._array[index], self._array[higher_index] = self._array[higher_index], self._array[index] index = higher_index def enumerate(self): """ Return the enumeration of a heap. Returns: Enumeration of a heap. """ return enumerate(self._array) def count(self) -> int: """ Return the number of items in the heap. Returns: The number of items in the heap. """ return len(self._array) def is_empty(self) -> bool: """ Check if a heap has any items. Returns: True if heap has no items. False if heap has more than 0 items. """ return self.count() == 0 def print(self): """ Print the contents of a heap. """ node_count = 1 for i in range(self.count()): if i + 1 >= node_count: print() node_count *= 2 print(self._array[i], end=" ") def __repr__(self): """ Return string representation of a heap in order of priority. """ temp_array = self._array[:] result = [] while not self.is_empty(): result.append(str(self.pop())) self._array = temp_array return "[" + " ".join(result) + "]" def __len__(self): """ Get the number of items in the priority queue. Returns: Number of items in the priority queue """ return self.count()
Subclasses
Static methods
def from_list(mylist: list)
-
Expand source code
@classmethod def from_list(cls, mylist: list): hp = cls() for e in mylist: hp.insert(e) return hp
Methods
def count(self) ‑> int
-
Return the number of items in the heap.
Returns
The number of items in the heap.
Expand source code
def count(self) -> int: """ Return the number of items in the heap. Returns: The number of items in the heap. """ return len(self._array)
def enumerate(self)
-
Return the enumeration of a heap.
Returns
Enumeration of a heap.
Expand source code
def enumerate(self): """ Return the enumeration of a heap. Returns: Enumeration of a heap. """ return enumerate(self._array)
def has_left(self, index: int) ‑> bool
-
Check if current node has an left child.
Args
index
:int
- The index of the node.
Returns
Boolean on whether a node has a left child node.
Expand source code
def has_left(self, index: int) -> bool: """ Check if current node has an left child. Args: index (int): The index of the node. Returns: Boolean on whether a node has a left child node. """ return self.left_index(index) < self.count()
def has_parent(self, index: int) ‑> bool
-
Check if a node has a parent node.
Args
index
:int
- The index of the node.
Returns
Boolean on whether a node has a parent node.
Expand source code
def has_parent(self, index: int) -> bool: """ Check if a node has a parent node. Args: index (int): The index of the node. Returns: Boolean on whether a node has a parent node. """ return self.parent_index(index) >= 0
def has_right(self, index: int) ‑> bool
-
Check if current node has an right child.
Args
index
:int
- The index of the node.
Returns
Boolean on whether a node has a right child node.
Expand source code
def has_right(self, index: int) -> bool: """ Check if current node has an right child. Args: index (int): The index of the node. Returns: Boolean on whether a node has a right child node. """ return self.right_index(index) < self.count()
def heapify_down(self, index: int)
-
Perform heapify down starting at a given index.
Args
index
:int
- The starting index.
Expand source code
def heapify_down(self, index: int): """ Perform heapify down starting at a given index. Args: index (int): The starting index. """ while self.has_left(index): higher_index = self.left_index(index) right_index = self.right_index(index) if self.has_right(index) and self._array[right_index] > self._array[higher_index]: higher_index = right_index if self._array[index] > self._array[higher_index]: break else: self._array[index], self._array[higher_index] = self._array[higher_index], self._array[index] index = higher_index
def heapify_up(self, index: int)
-
Perform heapify up starting at a given index.
Args
index
:int
- The starting index.
Expand source code
def heapify_up(self, index: int): """ Perform heapify up starting at a given index. Args: index (int): The starting index. """ parent_index = self.parent_index(index) while self.has_parent(index) and self._array[index] > self._array[parent_index]: self._array[index], self._array[parent_index] = self._array[parent_index], self._array[index] index = parent_index parent_index = self.parent_index(index)
def insert(self, value)
-
Insert a value into the heap.
Args
value
- The value to insert.
Expand source code
def insert(self, value): """ Insert a value into the heap. Args: value: The value to insert. """ self._array.append(value) start_index = self.count() - 1 self.heapify_up(start_index)
def is_empty(self) ‑> bool
-
Check if a heap has any items.
Returns
True if heap has no items. False if heap has more than 0 items.
Expand source code
def is_empty(self) -> bool: """ Check if a heap has any items. Returns: True if heap has no items. False if heap has more than 0 items. """ return self.count() == 0
def last(self)
-
Get the last node of the max heap.
Returns
The last node's value. None if count is 0.
Expand source code
def last(self): """ Get the last node of the max heap. Returns: The last node's value. None if count is 0. """ if self.count() == 0: return None return self._array[-1]
def left_index(self, index: int) ‑> int
-
Get the index of the left child.
Args
index
:int
- The index of the node.
Returns
Return the index of the left child.
Expand source code
def left_index(self, index: int) -> int: """ Get the index of the left child. Args: index (int): The index of the node. Returns: Return the index of the left child. """ return (index * 2) + 1
def parent_index(self, index: int) ‑> int
-
Get the index of the parent node.
Args
index
:int
- The index of the node.
Returns
Return the index of the parent child.
Expand source code
def parent_index(self, index: int) -> int: """ Get the index of the parent node. Args: index (int): The index of the node. Returns: Return the index of the parent child. """ return (index - 1) // 2
def peek(self)
-
Get the max value of the max heap.
Returns
The maximum value of the max heap.
Expand source code
def peek(self): """ Get the max value of the max heap. Returns: The maximum value of the max heap. """ return self.root()
def pop(self)
-
Return the value of the root node (max value) and remove it from the heap.
Returns
Return the value from the root node.
Expand source code
def pop(self): """ Return the value of the root node (max value) and remove it from the heap. Returns: Return the value from the root node. """ root_value = self.root() # start at root node start_index = 0 if self.count() == 0: raise Exception("Heap is empty") if self.count() == 1: self._array.pop() else: self._array[start_index] = self._array.pop() self.heapify_down(start_index) return root_value
def print(self)
-
Print the contents of a heap.
Expand source code
def print(self): """ Print the contents of a heap. """ node_count = 1 for i in range(self.count()): if i + 1 >= node_count: print() node_count *= 2 print(self._array[i], end=" ")
def right_index(self, index: int) ‑> int
-
Get the index of the right child.
Args
index
:int
- The index of the node.
Returns
Return the index of the right child.
Expand source code
def right_index(self, index: int) -> int: """ Get the index of the right child. Args: index (int): The index of the node. Returns: Return the index of the right child. """ return (index * 2) + 2
def root(self)
-
Get the root value.
Returns
The root node's value. None if count is 0.
Expand source code
def root(self): """ Get the root value. Returns: The root node's value. None if count is 0. """ if self.count() == 0: return None return self._array[0]
def to_list(self) ‑> list
-
Expand source code
def to_list(self) -> list: return self._array
class MinHeap
-
A max heap implementation.
Expand source code
class MinHeap(Heap): def heapify_up(self, index: int): """ Perform heapify up starting at a given index. Args: index (int): The starting index. """ parent_index = self.parent_index(index) while self.has_parent(index) and self._array[index] < self._array[parent_index]: self._array[index], self._array[parent_index] = self._array[parent_index], self._array[index] index = parent_index parent_index = self.parent_index(index) def heapify_down(self, index: int): """ Perform heapify down starting at a given index. Args: index (int): The starting index. """ while self.has_left(index): higher_index = self.left_index(index) right_index = self.right_index(index) if self.has_right(index) and self._array[right_index] < self._array[higher_index]: higher_index = right_index if self._array[index] < self._array[higher_index]: break else: self._array[index], self._array[higher_index] = self._array[higher_index], self._array[index] index = higher_index
Ancestors
Subclasses
Inherited members
class PriorityQueue
-
A priority queue implementation in Python.
Expand source code
class PriorityQueue(MinHeap): """ A priority queue implementation in Python. """ def push(self, priority: int, item): """ Insert an item with a priority into the priority queue. Args: priority (int): Priority of item. item: The item to insert. """ super().insert((priority, item)) def pop(self): """ Return and remove the highest priority value in the heap. Returns: Return The highest priority value in the heap. """ priority, item = super().pop() return item def pop_pair(self) -> tuple: """ Return and remove the highest priority value pair in the heap. Returns: Return the highest priority, value pair (tuple) in the heap. """ return super().pop() def peek(self): """ Return the highest priority value in the heap. Returns: Return The highest priority value in the heap. """ priority, item = super().peek() return item def peek_pair(self) -> tuple: """ Return the highest priority value pair in the heap. Returns: Return the highest priority, value pair (tuple) in the heap. """ return super().peek() def to_string_with_priority(self): """ Return string representation of a heap in order of priority. """ temp_array = self._array[:] result = [] while not self.is_empty(): result.append(str(self.pop_pair())) self._array = temp_array return "[" + " ".join(result) + "]"
Ancestors
Methods
def peek(self)
-
Return the highest priority value in the heap.
Returns
Return The highest priority value in the heap.
Expand source code
def peek(self): """ Return the highest priority value in the heap. Returns: Return The highest priority value in the heap. """ priority, item = super().peek() return item
def peek_pair(self) ‑> tuple
-
Return the highest priority value pair in the heap.
Returns
Return the highest priority, value pair (tuple) in the heap.
Expand source code
def peek_pair(self) -> tuple: """ Return the highest priority value pair in the heap. Returns: Return the highest priority, value pair (tuple) in the heap. """ return super().peek()
def pop(self)
-
Return and remove the highest priority value in the heap.
Returns
Return The highest priority value in the heap.
Expand source code
def pop(self): """ Return and remove the highest priority value in the heap. Returns: Return The highest priority value in the heap. """ priority, item = super().pop() return item
def pop_pair(self) ‑> tuple
-
Return and remove the highest priority value pair in the heap.
Returns
Return the highest priority, value pair (tuple) in the heap.
Expand source code
def pop_pair(self) -> tuple: """ Return and remove the highest priority value pair in the heap. Returns: Return the highest priority, value pair (tuple) in the heap. """ return super().pop()
def push(self, priority: int, item)
-
Insert an item with a priority into the priority queue.
Args
priority
:int
- Priority of item.
item
- The item to insert.
Expand source code
def push(self, priority: int, item): """ Insert an item with a priority into the priority queue. Args: priority (int): Priority of item. item: The item to insert. """ super().insert((priority, item))
def to_string_with_priority(self)
-
Return string representation of a heap in order of priority.
Expand source code
def to_string_with_priority(self): """ Return string representation of a heap in order of priority. """ temp_array = self._array[:] result = [] while not self.is_empty(): result.append(str(self.pop_pair())) self._array = temp_array return "[" + " ".join(result) + "]"
Inherited members