From b5a3a3a11e8151a121d817b04924699c702770b5 Mon Sep 17 00:00:00 2001 From: sarahstandish Date: Thu, 12 May 2022 13:16:50 -0700 Subject: [PATCH] passing tests --- heaps/heap_sort.py | 27 ++++++-- heaps/min_heap.py | 141 ++++++++++++++++++++++++++++++++--------- tests/test_heapsort.py | 4 ++ 3 files changed, 138 insertions(+), 34 deletions(-) diff --git a/heaps/heap_sort.py b/heaps/heap_sort.py index 3b834a5..43d04fe 100644 --- a/heaps/heap_sort.py +++ b/heaps/heap_sort.py @@ -1,8 +1,25 @@ +from .min_heap import MinHeap - -def heap_sort(list): +def heap_sort(l): """ 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(l) <= 1: + return l + + heap = MinHeap() + + for item in l: + heap.add(item) + + sorted = [] + + while heap.store: + item = heap.remove() + sorted.append(item) + + return sorted + +l = [5, 27, 3, 16, 50] +heap_sort(l) \ No newline at end of file diff --git a/heaps/min_heap.py b/heaps/min_heap.py index f6fe4e0..3c269cc 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 @@ -19,10 +19,42 @@ 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) where n is the length of self.store (??) + Space Complexity: O(1) + """ + if not value: + value = key + + node = HeapNode(key, value) + self.store.append(node) + self.heap_up(len(self.store) - 1) + + def heap_up(self, index): + """ This helper method takes an index and + moves the corresponding element up the heap, if + it is less than it's parent node until the Heap + property is reestablished. + + This could be **very** helpful for the add method. + Time complexity: O(log n) where n is the length of self.store (??) + Space complexity: O(1) """ - pass + if index == 0: + return + + curr = self.store[index] + if index % 2 == 0: + parent_index = (index // 2) - 1 + else: + parent_index = index // 2 + + parent_node = self.store[parent_index] + + if parent_node.key > curr.key: + self.swap(index, parent_index) + self.heap_up(parent_index) + else: + return def remove(self): """ This method removes and returns an element from the heap @@ -30,10 +62,54 @@ def remove(self): Time Complexity: ? Space Complexity: ? """ - pass + if self.empty(): + return None + self.swap(0, len(self.store) - 1) + + removed = self.store.pop() + + self.heap_down(0) + + return removed.value + + 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. + """ + if index >= len(self.store) - 1: + return + + curr = self.store[index] + + left_child_index = 2 * index + 1 + right_child_index = 2 * index + 2 + + if left_child_index >= len(self.store): + left_child_index = None + if right_child_index >= len(self.store): + right_child_index = None + + if not left_child_index and not right_child_index: + return + elif not left_child_index: + compare_index = right_child_index + elif not right_child_index: + compare_index = left_child_index + else: + left_child = self.store[left_child_index] + right_child = self.store[right_child_index] + compare_index = left_child_index if left_child.key < right_child.key else right_child_index + + compare_node = self.store[compare_index] + if curr.key > compare_node.key: + self.swap(compare_index, index) + self.heap_down(compare_index) + else: + return - def __str__(self): """ This method lets you print the heap, when you're testing your app. """ @@ -44,31 +120,13 @@ 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 False - def heap_up(self, index): - """ This helper method takes an index and - moves the corresponding element up the heap, if - it is less than it's parent node until the Heap - property is reestablished. - - This could be **very** helpful for the add method. - Time complexity: ? - Space complexity: ? - """ - pass - - 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. - """ - pass + return True def swap(self, index_1, index_2): @@ -79,3 +137,28 @@ 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(l): + """ This method uses a heap to sort an array. + Time Complexity: O(n log n) + Space Complexity: O(n) + """ + if len(l) <= 1: + return l + + heap = MinHeap() + + for item in l: + heap.add(item) + + sorted = [] + + while heap.store: + item = heap.remove() + sorted.append(item) + + return sorted + +l = [5, 27, 3, 16, 50] +heap_sort(l) \ No newline at end of file diff --git a/tests/test_heapsort.py b/tests/test_heapsort.py index 51b0c2e..76c80d7 100644 --- a/tests/test_heapsort.py +++ b/tests/test_heapsort.py @@ -1,4 +1,5 @@ from heaps.heap_sort import heap_sort +from tests.test_min_heap import heap def test_it_sorts_an_empty_list(): assert heap_sort([]) == [] @@ -15,3 +16,6 @@ def test_it_can_sort_a_5_element_list(): # Assert assert result == [3, 5, 16, 27, 50] + +l = [5, 27, 3, 16, 50] +heap_sort(l) \ No newline at end of file