diff --git a/heaps/heap_sort.py b/heaps/heap_sort.py index 3b834a5..1f007fa 100644 --- a/heaps/heap_sort.py +++ b/heaps/heap_sort.py @@ -1,8 +1,18 @@ - +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 Complexity: O(n) """ - pass \ No newline at end of file + + heap = MinHeap() + for element in list: + heap.add(element) + + index = 0 + while not heap.empty(): + list[index] = heap.remove() + index += 1 + + return list \ No newline at end of file diff --git a/heaps/min_heap.py b/heaps/min_heap.py index f6fe4e0..f690bb4 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -1,5 +1,5 @@ class HeapNode: - + def __init__(self, key, value): self.key = key self.value = value @@ -15,28 +15,52 @@ class MinHeap: def __init__(self): self.store = [] + # helpers + def parent_index(self, index): + return (index - 1) // 2 + + def left_child_index(self, index): + return (2 * index) + 1 + + def right_child_index(self, index): + return (2 * index) + 2 + 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(1) """ - pass + + if value is None: + value = key + + new_node = HeapNode(key, value) + self.store.append(new_node) + 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(1) """ - pass + + if len(self.store) == 0: + return + + self.swap(0, len(self.store) - 1) + min = self.store.pop() + self.heap_down(0) + + return min.value - def __str__(self): - """ This method lets you print the heap, when you're testing your app. - """ + """ This method lets you print the heap, when you're testing your app.""" + if len(self.store) == 0: return "[]" return f"[{', '.join([str(element) for element in self.store])}]" @@ -44,10 +68,10 @@ 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): @@ -57,10 +81,17 @@ def heap_up(self, index): property is reestablished. This could be **very** helpful for the add method. - Time complexity: ? - Space complexity: ? + Time complexity: O(log n) + Space complexity: O(1) """ - pass + + if index == 0: + return + + if self.store[self.parent_index(index)].key > self.store[index].key: + self.swap(self.parent_index(index), index) + self.heap_up(self.parent_index(index)) + def heap_down(self, index): """ This helper method takes an index and @@ -68,7 +99,18 @@ def heap_down(self, index): larger than either of its children and continues until the heap property is reestablished. """ - pass + + if self.left_child_index(index) < len(self.store): + if self.right_child_index(index) < len(self.store): + if self.store[self.left_child_index(index)].key < self.store[self.right_child_index(index)].key: + smaller_node = self.left_child_index(index) + else: + smaller_node = self.right_child_index(index) + else: + smaller_node = self.left_child_index(index) + if self.store[index].key > self.store[smaller_node].key: + self.swap(index, smaller_node) + self.heap_down(smaller_node) def swap(self, index_1, index_2): @@ -76,6 +118,6 @@ def swap(self, index_1, index_2): at index_1 and index_2 used for heap_up & heap_down """ - temp = self.store[index_1] - self.store[index_1] = self.store[index_2] - self.store[index_2] = temp + + self.store[index_1], self.store[index_2] = self.store[index_2], self.store[index_1] +