diff --git a/heaps/heap_sort.py b/heaps/heap_sort.py index 3b834a5..ce5d51f 100644 --- a/heaps/heap_sort.py +++ b/heaps/heap_sort.py @@ -1,8 +1,22 @@ +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 + if len(list) <= 1: + return list + + heap = MinHeap() + + for item in list: + heap.add(item) + + return_list = [] + while not heap.empty(): + return_list.append(heap.remove()) + + return return_list + diff --git a/heaps/min_heap.py b/heaps/min_heap.py index f6fe4e0..5d01032 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -1,3 +1,6 @@ +from cgitb import small + + class HeapNode: def __init__(self, key, value): @@ -19,35 +22,47 @@ 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 + item = HeapNode(key, value) + self.store.append(item) + 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 self.empty(): + return None + + self.swap(0, -1) + + removed_value = self.store.pop() + self.heap_down(0) + + return removed_value.value def __str__(self): """ This method lets you print the heap, when you're testing your app. """ - if len(self.store) == 0: + if self.empty(): return "[]" return f"[{', '.join([str(element) for element in self.store])}]" 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 not self.store def heap_up(self, index): @@ -57,10 +72,19 @@ 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(log n) """ - pass + if self.empty(): + return + + if index != 0: + compare_index = (index - 1) // 2 + if self.store[index].key < self.store[compare_index].key: + self.swap(index, compare_index) + self.heap_up(compare_index) + + return def heap_down(self, index): """ This helper method takes an index and @@ -68,8 +92,43 @@ def heap_down(self, index): larger than either of its children and continues until the heap property is reestablished. """ - pass + if self.empty(): + return + + left_child_index = index * 2 + 1 + right_child_index = index * 2 + 2 + + if left_child_index < len(self.store): + if right_child_index < len(self.store): + if self.is_left_index_smaller(left_child_index, right_child_index): + # smaller_value = self.find_smaller_key(right_child_index, left_child_index) + # if smaller_value == left_child_index: + self.swap(index, left_child_index) + self.heap_down(left_child_index) + else: + if self.store[index].key > self.store[right_child_index].key: + self.swap(index, right_child_index) + self.heap_down(right_child_index) + else: + if self.is_left_index_smaller(left_child_index, index): + self.swap(index, left_child_index) + self.heap_down(left_child_index) + + return + +# I started with this helper method, but then switched to the other one + # def find_smaller_key(self, index_1, index_2): + # if self.store[index_1].key < self.store[index_2].key: + # return index_1 + # else: + # return index_2 +# I know this isn't that helpful, but it helped me make more sense of what was happening +# in the heap_down method + def is_left_index_smaller(self, index_1, index_2): + if self.store[index_1].key < self.store[index_2].key: + return True + return False def swap(self, index_1, index_2): """ Swaps two elements in self.store