From d037e1ae81e1efb480d7aeed931f1c9986dedf24 Mon Sep 17 00:00:00 2001 From: evangeline spracklin Date: Thu, 21 Jul 2022 14:24:34 -0700 Subject: [PATCH 1/3] min heap functions (except remove) --- heaps/min_heap.py | 74 +++++++++++++++++++++++++++++++++++++----- tests/test_min_heap.py | 3 +- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/heaps/min_heap.py b/heaps/min_heap.py index f6fe4e0..6a3d4a4 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -22,7 +22,12 @@ def add(self, key, value = None): Time Complexity: ? Space Complexity: ? """ - 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 @@ -31,8 +36,16 @@ def remove(self): Space Complexity: ? """ pass - - + if len(self.store) == 0: + return None + top_node = self.store[0] + #swap first and last + self.swap(0, -1) + #remove last + result = self.store.pop() + while self.empty() == False: + self.heap_down(0) + return result def __str__(self): """ This method lets you print the heap, when you're testing your app. @@ -44,10 +57,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): @@ -57,10 +72,21 @@ def heap_up(self, index): property is reestablished. This could be **very** helpful for the add method. - Time complexity: ? + Time complexity: ? O(log n) Space complexity: ? """ - pass + parent_index = int((index - 1) / 2) + current_key = self.store[index].key + parent_key = self.store[parent_index].key + # print(f"parent key is {parent_key}") + # print(f"current key is {current_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 heap_down(self, index): """ This helper method takes an index and @@ -68,7 +94,24 @@ def heap_down(self, index): larger than either of its children and continues until the heap property is reestablished. """ - pass + # i need to figure out how to ensure that an index is within bounds + + # left child + if index <= len(self.store) - 1 and int((2 * index) + 1) <= len(self.store) - 1: + while self.store[index].key > self.store[int((2 * index) + 1)].key: + self.swap(index, int((2 * index) + 1)) + index = int((2 * 1) + 1) + if index > len(self.store) - 1 or int((2 * index) + 1) > len(self.store) - 1: + break + + #right child + # while self.store[index].key > self.store[int((2 * index) + 2)].key: + # self.swap(index, int((2 * index) + 2)) + # index = int((2 * index) + 2) + # if index > len(self.store) - 1: + # break + + return def swap(self, index_1, index_2): @@ -79,3 +122,16 @@ 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 + +# some_heap = MinHeap() +# some_heap.add(3, "Pasta") +# some_heap.add(6, "Soup") +# some_heap.add(1, "Pizza") +# some_heap.add(0, "Donuts") +# some_heap.add(16, "Cookies") +# some_heap.add(57, "Cake") +# print(some_heap.store) +# for item in some_heap.store: +# print(item.value) +# some_heap.remove() +# print(some_heap.store) \ No newline at end of file diff --git a/tests/test_min_heap.py b/tests/test_min_heap.py index 5ec272c..fefba48 100644 --- a/tests/test_min_heap.py +++ b/tests/test_min_heap.py @@ -69,7 +69,6 @@ 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"] @@ -77,4 +76,4 @@ def test_it_can_remove_nodes_in_proper_order(heap): 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 From bda00cbc7e539f97b814ec74bb179443f71bffcc Mon Sep 17 00:00:00 2001 From: evangeline spracklin Date: Thu, 21 Jul 2022 17:15:22 -0700 Subject: [PATCH 2/3] remove function works --- heaps/min_heap.py | 75 ++++++++++++++++++++++++------------------ tests/test_min_heap.py | 1 + 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/heaps/min_heap.py b/heaps/min_heap.py index 6a3d4a4..2f17eaf 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -35,17 +35,14 @@ def remove(self): Time Complexity: ? Space Complexity: ? """ - pass - if len(self.store) == 0: - return None + if self.empty(): + return top_node = self.store[0] - #swap first and last self.swap(0, -1) - #remove last result = self.store.pop() - while self.empty() == False: + if not self.empty(): self.heap_down(0) - return result + return str(result) def __str__(self): """ This method lets you print the heap, when you're testing your app. @@ -88,29 +85,34 @@ def heap_up(self, index): 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. """ - # i need to figure out how to ensure that an index is within bounds - - # left child - if index <= len(self.store) - 1 and int((2 * index) + 1) <= len(self.store) - 1: - while self.store[index].key > self.store[int((2 * index) + 1)].key: - self.swap(index, int((2 * index) + 1)) - index = int((2 * 1) + 1) - if index > len(self.store) - 1 or int((2 * index) + 1) > len(self.store) - 1: - break - - #right child - # while self.store[index].key > self.store[int((2 * index) + 2)].key: - # self.swap(index, int((2 * index) + 2)) - # index = int((2 * index) + 2) - # if index > len(self.store) - 1: - # break - + 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 @@ -123,15 +125,24 @@ def swap(self, index_1, index_2): self.store[index_1] = self.store[index_2] self.store[index_2] = temp -# some_heap = MinHeap() -# some_heap.add(3, "Pasta") -# some_heap.add(6, "Soup") -# some_heap.add(1, "Pizza") -# some_heap.add(0, "Donuts") -# some_heap.add(16, "Cookies") -# some_heap.add(57, "Cake") +some_heap = MinHeap() +some_heap.add(3, "Pasta") +some_heap.add(6, "Soup") +some_heap.add(1, "Pizza") +some_heap.add(0, "Donuts") +some_heap.add(16, "Cookies") +some_heap.add(57, "Cake") # print(some_heap.store) # for item in some_heap.store: # print(item.value) # some_heap.remove() -# print(some_heap.store) \ No newline at end of file +# print(some_heap.store) +print(some_heap.store) +i = 2 +print(f"{some_heap.store[i]} has a left child: {some_heap.has_left_child(i)}") +print(f"{some_heap.store[i]} has a right child: {some_heap.has_right_child(i)}") +print("K! gonna remooooove") +some_heap.remove() +print(some_heap.store) +print(f"{some_heap.store[i]} has a left child: {some_heap.has_left_child(i)}") +print(f"{some_heap.store[i]} has a right child: {some_heap.has_right_child(i)}") \ No newline at end of file diff --git a/tests/test_min_heap.py b/tests/test_min_heap.py index fefba48..5d47791 100644 --- a/tests/test_min_heap.py +++ b/tests/test_min_heap.py @@ -71,6 +71,7 @@ def test_it_can_remove_nodes_in_proper_order(heap): # Act returned_items = ["Donuts", "Pizza", "Pasta", "Soup", "Cookies", "Cake"] + # assert heap.store == returned_items for item in returned_items: assert heap.remove() == item From 1d3edf2fc24fcb5fd0b98f586a12486ef5bac829 Mon Sep 17 00:00:00 2001 From: evangeline spracklin Date: Thu, 21 Jul 2022 18:46:26 -0700 Subject: [PATCH 3/3] solves heap_sort function --- heaps/heap_sort.py | 103 +++++++++++++++++++++++++++++++++++++++++++-- heaps/min_heap.py | 42 ++++-------------- 2 files changed, 108 insertions(+), 37 deletions(-) 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 2f17eaf..8071b6a 100644 --- a/heaps/min_heap.py +++ b/heaps/min_heap.py @@ -19,8 +19,8 @@ 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) """ if value == None: value = key @@ -32,12 +32,11 @@ def add(self, key, value = None): 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) """ if self.empty(): return - top_node = self.store[0] self.swap(0, -1) result = self.store.pop() if not self.empty(): @@ -61,7 +60,6 @@ def empty(self): return True return False - def heap_up(self, index): """ This helper method takes an index and moves the corresponding element up the heap, if @@ -70,13 +68,11 @@ def heap_up(self, index): This could be **very** helpful for the add method. Time complexity: ? O(log n) - Space complexity: ? + Space complexity: ? O(1) """ parent_index = int((index - 1) / 2) current_key = self.store[index].key parent_key = self.store[parent_index].key - # print(f"parent key is {parent_key}") - # print(f"current key is {current_key}") while current_key < parent_key: self.swap(index, parent_index) @@ -97,12 +93,13 @@ def has_right_child(self, index): 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) """ if self.has_left_child(index) and (self.store[index].key > self.store[int((2 * index) + 1)].key): left_child_index = (2 * index) + 1 @@ -114,8 +111,7 @@ def heap_down(self, index): 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 @@ -124,25 +120,3 @@ 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 - -some_heap = MinHeap() -some_heap.add(3, "Pasta") -some_heap.add(6, "Soup") -some_heap.add(1, "Pizza") -some_heap.add(0, "Donuts") -some_heap.add(16, "Cookies") -some_heap.add(57, "Cake") -# print(some_heap.store) -# for item in some_heap.store: -# print(item.value) -# some_heap.remove() -# print(some_heap.store) -print(some_heap.store) -i = 2 -print(f"{some_heap.store[i]} has a left child: {some_heap.has_left_child(i)}") -print(f"{some_heap.store[i]} has a right child: {some_heap.has_right_child(i)}") -print("K! gonna remooooove") -some_heap.remove() -print(some_heap.store) -print(f"{some_heap.store[i]} has a left child: {some_heap.has_left_child(i)}") -print(f"{some_heap.store[i]} has a right child: {some_heap.has_right_child(i)}") \ No newline at end of file