Skip to content

Commit

Permalink
Converted BinaryHeap to be a ABCMeta class
Browse files Browse the repository at this point in the history
- Removed tests for BinaryHeap
- Fixed other minor things around
  • Loading branch information
nbro committed Feb 14, 2017
1 parent 1449a03 commit 681a9fb
Show file tree
Hide file tree
Showing 18 changed files with 93 additions and 66 deletions.
31 changes: 17 additions & 14 deletions ands/ds/Heap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Created: 01/07/2015
Updated: 13/02/2017
Updated: 14/02/2017
# Description
Expand All @@ -22,10 +22,13 @@
- Chapter 13 of [Introduction to Algorithms (3rd ed.)](https://mitpress.mit.edu/books/introduction-algorithms) by CLRS
- [NotImplementedError](https://docs.python.org/3/library/exceptions.html#NotImplementedError)
- [How do I check if an object is an instance of a given class or of a subclass of it?](http://effbot.org/pyfaq/how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it.htm)
- [https://en.wikipedia.org/wiki/Heap_(data_structure)](https://en.wikipedia.org/wiki/Heap_(data_structure))
"""

import io
import math
from abc import ABCMeta, abstractmethod

__all__ = ["BinaryHeap", "HeapNode", "build_pretty_binary_heap"]

Expand Down Expand Up @@ -67,7 +70,7 @@ def __repr__(self):
return str(self.value) + " -> " + str(self.key)


class BinaryHeap:
class BinaryHeap(metaclass=ABCMeta):
"""Abstract class to represent binary heaps.
`MinHeap`, `MaxHeap` and `MinMaxHeap` all derive from this class."""
Expand All @@ -78,27 +81,32 @@ def __init__(self, ls=None):
self.heap = BinaryHeap._create_list_of_heap_nodes(ls)
self.build_heap()

@abstractmethod
def push_down(self, i: int) -> None:
"""Classical so-called heapify operation for heaps."""
raise NotImplementedError()
"""Classical _heapify_ operation for heaps."""
pass

@abstractmethod
def push_up(self, i: int) -> None:
"""Classical reverse-heapify operation for heaps."""
raise NotImplementedError()
pass

@abstractmethod
def delete(self, i: int) -> HeapNode:
raise NotImplementedError()
"""Deletes from self element at index `i` and returns it."""
pass

@abstractmethod
def replace(self, i: int, x) -> HeapNode:
"""Replaces the `HeapNode` object at index `i` with `x`.
`x` can either be a key or a `HeapNode` object.
If it's a key, an `HeapNode` is first created,
whose key and value are equal to `x`."""
raise NotImplementedError()
pass

def build_heap(self) -> list:
"""Builds the heap data structure from `self.heap`."""
"""Builds the heap data structure."""
if self.heap:
for index in range(len(self.heap) // 2, -1, -1):
self.push_down(index)
Expand Down Expand Up @@ -211,8 +219,6 @@ def swap(self, i: int, j: int) -> None:
else:
raise IndexError("i or j are not valid indexes.")

# INDEX FUNCTIONS

def is_good_index(self, i: int) -> bool:
"""Returns `True` if `i` is valid index for `self.heap`,
`False` otherwise.
Expand Down Expand Up @@ -382,12 +388,11 @@ def build_pretty_binary_heap(heap: list, total_width=36, fill=" ") -> str:

output = io.StringIO()
last_row = -1

h_space = 3.0 # float
v_space = 2 # int

for i, heap_node in enumerate(heap):
if i:
if i != 0:
row = int(math.floor(math.log(i + 1, 2)))
else:
row = 0
Expand All @@ -396,13 +401,11 @@ def build_pretty_binary_heap(heap: list, total_width=36, fill=" ") -> str:
output.write("\n" * v_space)

columns = 2 ** row

column_width = int(math.floor((total_width * h_space) / columns))
output.write(str(heap_node).center(column_width, fill))
last_row = row

s = output.getvalue() + "\n"

line_length = total_width + 15 # int
s += ('-' * line_length + "\n")
return s
4 changes: 2 additions & 2 deletions ands/ds/MaxHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Created: 15/02/2016
Updated: 05/02/2017
Updated: 14/02/2017
# Description
Expand Down Expand Up @@ -140,7 +140,7 @@ def replace(self, i: int, x) -> HeapNode:
return c


def is_max_heap(h) -> bool:
def is_max_heap(h: MaxHeap) -> bool:
"""Returns `True` if `h` is a valid `MaxHeap`. `False` otherwise."""
if not isinstance(h, MaxHeap):
return False
Expand Down
4 changes: 2 additions & 2 deletions ands/ds/MinHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Created: 01/07/2015
Updated: 05/02/2017
Updated: 14/02/2017
# Description
Expand Down Expand Up @@ -161,7 +161,7 @@ def replace(self, i: int, x) -> HeapNode:
return c


def is_min_heap(h) -> bool:
def is_min_heap(h: MinHeap) -> bool:
"""Returns `True` if `h` is a valid `MinHeap`. `False` otherwise."""
if not isinstance(h, MinHeap):
return False
Expand Down
37 changes: 20 additions & 17 deletions ands/ds/MinMaxHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Created: 18/02/2016
Updated: 29/12/2016
Updated: 14/02/2017
# Description
Expand All @@ -25,7 +25,22 @@
Even levels are 0, 2, 4, 6, etc,
whereas odd levels are 1, 3, 5, 7, etc.
The most important methods used to build and support the data structure are:
The public API of this class consists in the following methods:
- add in O(log n) time
- delete-at in O(log n) time
- replace-at in O(log n) time
- remove-min in O(log n) time
- remove-max in O(log n) time
- find-min in O(1) time
- find-max in O(1) time
- size in O(1) time
- is-empty in O(1) time
- contains in O(n) time
- merge in O(n + m) time
- clear in O(1) time
And the following are the methods used to build and support the data structure (i.e. the previous operations):
- trickle-down (or, also called, bubble-down or shift-down)
- trickle-down-min, which is a helper method of trickle-down
Expand All @@ -42,23 +57,11 @@
- find-max-element-index
- swap
- `add` in O(log n) time
- `delete-at` in O(log n) time
- `replace-at` in O(log n) time
- `remove-min` in O(log n) time
- `remove-max` in O(log n) time
- `find-min` in O(1) time
- `find-max` in O(1) time
- `size` in O(1) time
- `is-empty` in O(1) time
- `contains` in O(n) time
- `merge` in O(n + m) time
- `clear` in O(1) time
# TODO
- `find-kth`, i.e. find the kth smallest element in the structure, in O(1) time
- `delete-kth`, i.e. delete the kth smallest element, in O(log n) time
- find-kth, i.e. find the kth smallest element in the structure, in O(1) time
- delete-kth, i.e. delete the kth smallest element, in O(log n) time
# References
Expand Down Expand Up @@ -310,7 +313,7 @@ def index_of_max(self, i: int) -> int:
return m


def is_min_max_heap(h) -> bool:
def is_min_max_heap(h: MinMaxHeap) -> bool:
"""Returns `True` if `h` is a valid `MinMaxHeap` object. `False` otherwise.
Min-max heap property:
Expand Down
2 changes: 2 additions & 0 deletions tests/ds/test_BST.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# Meta info
Author: Nelson Brochado
Created: 13/02/2016
Updated: 30/08/2016
# Description
Expand Down
2 changes: 2 additions & 0 deletions tests/ds/test_BSTNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# Meta info
Author: Nelson Brochado
Created: 15/02/2016
Updated: 30/08/2016
# Description
Expand Down
26 changes: 0 additions & 26 deletions tests/ds/test_BinaryHeap.py

This file was deleted.

2 changes: 2 additions & 0 deletions tests/ds/test_DSForests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# Meta info
Author: Nelson Brochado
Created: 22/02/16
Updated: 03/01/17
# Description
Expand Down
2 changes: 2 additions & 0 deletions tests/ds/test_HeapNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
# Meta info
Author: Nelson Brochado
Created: 05/02/2017
Updated: 05/02/2017
# Description
Expand Down
4 changes: 2 additions & 2 deletions tests/ds/test_LinearProbingHashTable.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,13 @@ def test_show(self):
t = LinearProbingHashTable()
ls = sample(range(3), 3)
for elem in ls:
t.put(elem, choice(list(string.ascii_letters)))
t.put(elem, choice(string.ascii_letters))
print()
t.show()

def test_repr(self):
t = LinearProbingHashTable()
ls = sample(range(5), 5)
for elem in ls:
t.put(elem, choice(list(string.ascii_letters)))
t.put(elem, choice(string.ascii_letters))
print(repr(t))
12 changes: 11 additions & 1 deletion tests/ds/test_MaxHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
# Meta info
Author: Nelson Brochado
Created: 17/02/2016
Updated: 05/02/2017
Updated: 14/02/2017
# Description
Expand Down Expand Up @@ -524,3 +526,11 @@ def test_is_on_odd_level(self):
self.assertFalse(h.is_on_odd_level(6))
self.assertTrue(h.is_on_odd_level(7))
self.assertTrue(h.is_on_odd_level(8))

def test_str(self):
h = MaxHeap([12, 14, 28, 6, 7, 18, 10, 3, 1])
print(h)

def test_repr(self):
h = MaxHeap([1, 2, 3, 4, 5])
print(repr(h))
12 changes: 11 additions & 1 deletion tests/ds/test_MinHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
# Meta info
Author: Nelson Brochado
Created: 14/02/2016
Updated: 05/02/2017
Updated: 14/02/2017
# Description
Expand Down Expand Up @@ -582,3 +584,11 @@ def test_is_on_odd_level(self):
self.assertFalse(h.is_on_odd_level(6))
self.assertTrue(h.is_on_odd_level(7))
self.assertTrue(h.is_on_odd_level(8))

def test_str(self):
h = MinHeap([1, 2, 3, 4, 5])
print(h)

def test_repr(self):
h = MinHeap([1, 2, 3, 4, 5])
print(repr(h))
12 changes: 11 additions & 1 deletion tests/ds/test_MinMaxHeap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
# Meta info
Author: Nelson Brochado
Created: 20/02/2016
Updated: 05/02/2017
Updated: 14/02/2017
# Description
Expand Down Expand Up @@ -247,3 +249,11 @@ def test_index_of_min_and_max(self):
self.assertEqual(h.index_of_max(7), -1)
self.assertEqual(h.index_of_min(8), -1)
self.assertEqual(h.index_of_max(8), -1)

def test_str(self):
h = MinMaxHeap([7, 2, 92, 67])
print(h)

def test_repr(self):
h = MinMaxHeap([7, 2, 92, 67])
print(repr(h))
1 change: 1 addition & 0 deletions tests/ds/test_Queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Meta info
Author: Nelson Brochado
Created: 24/01/2017
# Description
Expand Down
2 changes: 2 additions & 0 deletions tests/ds/test_RBT.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# Meta info
Author: Nelson Brochado
Created: 15/02/2016
Updated: 08/10/2017
# Description
Expand Down
2 changes: 2 additions & 0 deletions tests/ds/test_Stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# Meta info
Author: Nelson Brochado
Created: 01/07/16
Updated: 04/02/2017
# Description
Expand Down
Loading

0 comments on commit 681a9fb

Please sign in to comment.