diff --git a/heaps/heap_sort.py b/heaps/heap_sort.py index 3b834a5..d5dcb2f 100644 --- a/heaps/heap_sort.py +++ b/heaps/heap_sort.py @@ -1,8 +1,105 @@ +''' i tried to import MinHeap from the other file but it wasn't passing pytest tests +this is what i was writing: +from min_heap import MinHeap + +anyway i copy and pasted the functions from previous work, but removed the Heap Node part since these tests just look at a list of numbers. + +see line 76 for the heap_sort function! + +''' + +class MinHeap: + + def __init__(self): + self.store = [] + + def add(self, key): + self.store.append(key) + last_index = len(self.store) - 1 + self.heap_up(last_index) + return + + def remove(self): + if self.empty(): + return + self.swap(0, -1) + result = self.store.pop() + if not self.empty(): + self.heap_down(0) + return result + + def empty(self): + if len(self.store) == 0: + return True + return False + + def heap_up(self, index): + parent_index = int((index - 1) / 2) + current = self.store[index] + parent = self.store[parent_index] + + while current < parent: + self.swap(index, parent_index) + index = parent_index + parent_index = int((index - 1) / 2) + current = self.store[index] + parent = self.store[parent_index] + + def has_left_child(self, index): + left_child_index = int((2 * index) + 1) + if left_child_index <= len(self.store) - 1: + return True + return False + + def has_right_child(self, index): + right_child_index = int((2 * index) + 2) + if right_child_index <= len(self.store) - 1: + return True + return False + + def heap_down(self, index): + if self.has_left_child(index) and (self.store[index] > self.store[int((2 * index) + 1)]): + left_child_index = (2 * index) + 1 + self.swap(index, left_child_index) + self.heap_down(left_child_index) + + if self.has_right_child(index) and (self.store[index] > self.store[int((2 * index) + 2)]): + right_child_index = (2 * index) + 2 + self.swap(index, right_child_index) + self.heap_down(right_child_index) + return + + def swap(self, index_1, index_2): + temp = self.store[index_1] + self.store[index_1] = self.store[index_2] + self.store[index_2] = temp def heap_sort(list): """ This method uses a heap to sort an array. - Time Complexity: ? - Space Complexity: ? + Time Complexity: ? O(n) + Space Complexity: ? O(n) """ - pass \ No newline at end of file + result = [] + if not list: + return result + + da_heap = MinHeap() + + for num in list: + da_heap.add(num) + + while len(result) != len(list): + top_of_heap = da_heap.remove() + result.append(top_of_heap) + + return result + + +nums = [5, 27, 3, 16, 50] +print(f"{nums} <---given nums") +result = heap_sort(nums) +print(f"{result} <---result of heap_sort") +expected = [3, 5, 16, 27, 50] +print(f"{expected} <--- expected result") +print(f"do they match? {result == expected}") \ No newline at end of file diff --git a/heaps/min_heap.py b/heaps/min_heap.py index f6fe4e0..8071b6a 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -19,20 +19,29 @@ 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(1) """ - pass + if value == None: + value = key + self.store.append(HeapNode(key, value)) + last_index = len(self.store) - 1 + self.heap_up(last_index) + return 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 self.empty(): + return + self.swap(0, -1) + result = self.store.pop() + if not self.empty(): + self.heap_down(0) + return str(result) def __str__(self): """ This method lets you print the heap, when you're testing your app. @@ -44,11 +53,12 @@ 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 - + if len(self.store) == 0: + return True + return False def heap_up(self, index): """ This helper method takes an index and @@ -57,20 +67,51 @@ 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 + parent_index = int((index - 1) / 2) + current_key = self.store[index].key + parent_key = self.store[parent_index].key + while current_key < parent_key: + self.swap(index, parent_index) + index = parent_index + parent_index = int((index - 1) / 2) + current_key = self.store[index].key + parent_key = self.store[parent_index].key + + def has_left_child(self, index): + left_child_index = int((2 * index) + 1) + if left_child_index <= len(self.store) - 1: + return True + return False + + def has_right_child(self, index): + right_child_index = int((2 * index) + 2) + if right_child_index <= len(self.store) - 1: + return True + return False + def heap_down(self, index): """ This helper method takes an index and moves the corresponding element down the heap if it's larger than either of its children and continues until the heap property is reestablished. + time complexity O(log n) + space complexity O(1) """ - pass + if self.has_left_child(index) and (self.store[index].key > self.store[int((2 * index) + 1)].key): + left_child_index = (2 * index) + 1 + self.swap(index, left_child_index) + self.heap_down(left_child_index) - + if self.has_right_child(index) and (self.store[index].key > self.store[int((2 * index) + 2)].key): + right_child_index = (2 * index) + 2 + self.swap(index, right_child_index) + self.heap_down(right_child_index) + return + def swap(self, index_1, index_2): """ Swaps two elements in self.store at index_1 and index_2 diff --git a/tests/test_min_heap.py b/tests/test_min_heap.py index 5ec272c..5d47791 100644 --- a/tests/test_min_heap.py +++ b/tests/test_min_heap.py @@ -69,12 +69,12 @@ def test_it_can_remove_nodes_in_proper_order(heap): heap.add(0, "Donuts") heap.add(16, "Cookies") - # Act returned_items = ["Donuts", "Pizza", "Pasta", "Soup", "Cookies", "Cake"] + # assert heap.store == returned_items for item in returned_items: assert heap.remove() == item def test_removing_a_node_from_an_empty_heap_is_none(heap): - assert heap.remove() == None + assert heap.remove() == None \ No newline at end of file