diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 37dfdde..43a1c57 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -6,9 +6,9 @@ Congratulations! You're submitting your assignment! Question | Answer :------------- | :------------- -How is a Heap different from a Binary Search Tree? | -Could you build a heap with linked nodes? | -Why is adding a node to a heap an O(log n) operation? | -Were the `heap_up` & `heap_down` methods useful? Why? | +How is a Heap different from a Binary Search Tree? | A BST is ordered; A Heap is not entirely ordered. And heaps allow duplicates, unlike BSTs +Could you build a heap with linked nodes? | uh, I guess you *could* but it would not be very efficient to search compared to a normal array +Why is adding a node to a heap an O(log n) operation? | Because it has to figure out where it truly belongs +Were the `heap_up` & `heap_down` methods useful? Why? | Because after big changes, they help every node and child find where to go. They restore balance to the heap. diff --git a/heaps/heap_sort.py b/heaps/heap_sort.py index 3b834a5..fb819c4 100644 --- a/heaps/heap_sort.py +++ b/heaps/heap_sort.py @@ -1,8 +1,19 @@ - +from heaps.min_heap import MinHeap def heap_sort(list): - """ This method uses a heap to sort an array. - Time Complexity: ? - Space Complexity: ? + """ + Time Complexity: O(n log n) + Space Complexitty: O(n) """ - pass \ No newline at end of file + listless = MinHeap() + sorts= [] + + for node in list: + listless.add(node) + + for i in range(len(list)): + nod = listless.remove() + sorts.append(nod) + + return sorts + diff --git a/heaps/min_heap.py b/heaps/min_heap.py index a1340e3..b884d57 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -1,9 +1,14 @@ class HeapNode: - def initialize(self, key, value): + def __init__(self, key, value): self.key = key self.value = value + def __str__(self): + return str(self.value) + + def __repr__(self): + return str(self.value) class MinHeap: @@ -14,19 +19,31 @@ def __init__(self): def add(self, key, value = None): """ This method adds a HeapNode instance to the heap If value == None the new node's value should be set to key - Time Complexity: ? - Space Complexity: ? + Time Complexity: O(log n) + Space Complexity: O(log n) """ - pass + if value == None: + value = key + + self.store.append(HeapNode(key, value)) + self.heap_up(len(self.store) - 1) + def remove(self): """ This method removes and returns an element from the heap maintaining the heap structure - Time Complexity: ? - Space Complexity: ? + Time Complexity: O(log n) + Space Complexity: O(log n) """ - pass + if len(self.store) == 0: + return None + caboose = len(self.store) - 1 + self.swap(0, caboose) + smol = self.store.pop() + + self.heap_down(0) + return smol.value def __str__(self): @@ -39,27 +56,50 @@ def __str__(self): def empty(self): """ This method returns true if the heap is empty - Time complexity: ? - Space complexity: ? + Time complexity: O(1) + Space complexity: O(1) """ - pass + return len(self.store) == 0 def heap_up(self, index): + """ This helper method takes an index and moves it up the heap, if it is less than it's parent node. It could be **very** helpful for the add method. - Time complexity: ? - Space complexity: ? + Time complexity: O(log n) + Space complexity: O(log n) """ - pass + if index == 0: + return + + parent = (index - 1) // 2 + store = self.store + if store[parent].key > store[index].key: + self.swap(parent, index) + self.heap_up(parent) + def heap_down(self, index): """ This helper method takes an index and moves it up the heap if it's smaller than it's parent node. """ - pass + children = index * 2 + 1 + left = children + right = children + 1 + if left < len(self.store): + if right < len(self.store): + if self.store[left].key < self.store[right].key: + smol = left + else: + smol = right + else: + smol = left + + if self.store[index].key > self.store[smol].key: + self.swap(index, smol) + self.heap_down(smol) def swap(self, index_1, index_2):