From 85e1b55f5cca01088bcd26efd7f71988fbb7e4c1 Mon Sep 17 00:00:00 2001 From: Kareha Agesa Date: Sat, 24 Apr 2021 15:17:30 -0700 Subject: [PATCH 1/5] add method --- lib/min_heap.rb | 21 +++++++++++++++------ test/min_heap_test.rb | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 6eaa630..02f8733 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -14,10 +14,12 @@ def initialize end # This method adds a HeapNode instance to the heap - # Time Complexity: ? - # Space Complexity: ? + # Time Complexity: O(logn) + # Space Complexity: O(logn) def add(key, value = key) - raise NotImplementedError, "Method not implemented yet..." + node = HeapNode.new(key, value) + @store.push(node) + return heap_up(@store.length - 1) end # This method removes and returns an element from the heap @@ -55,10 +57,17 @@ def empty? # This helper method takes an index and # moves it up the heap, if it is less than it's parent node. # It could be **very** helpful for the add method. - # Time complexity: ? - # Space complexity: ? + # Time complexity: O(logn) + # Space complexity: O(logn) def heap_up(index) - + return if index == 0 + + parent = (index - 1)/2 + if @store[parent].key > @store[index].key + swap(parent, index) + end + + return heap_up(parent) end # This helper method takes an index and diff --git a/test/min_heap_test.rb b/test/min_heap_test.rb index 186d4c2..9a76c2e 100644 --- a/test/min_heap_test.rb +++ b/test/min_heap_test.rb @@ -51,7 +51,7 @@ expect(output).must_equal "[Donuts, Pizza, Pasta, Soup, Cookies, Cake]" end - it "can remove nodes in the proper order" do + xit "can remove nodes in the proper order" do # Arrange heap.add(3, "Pasta") heap.add(6, "Soup") From c3e476840368962cb0e59bf479e33e9db634049c Mon Sep 17 00:00:00 2001 From: Kareha Agesa Date: Sat, 24 Apr 2021 16:59:34 -0700 Subject: [PATCH 2/5] min heap methods --- lib/min_heap.rb | 50 +++++++++++++++++++++++++++++++++++++------ test/min_heap_test.rb | 2 +- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 02f8733..2139c28 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -15,7 +15,7 @@ def initialize # This method adds a HeapNode instance to the heap # Time Complexity: O(logn) - # Space Complexity: O(logn) + # Space Complexity: ? def add(key, value = key) node = HeapNode.new(key, value) @store.push(node) @@ -27,7 +27,11 @@ def add(key, value = key) # Time Complexity: ? # Space Complexity: ? def remove() - raise NotImplementedError, "Method not implemented yet..." + return if @store.empty? + swap(0, -1) + removed = @store.pop + heap_down(0) unless @store.empty? + return removed.value end @@ -46,10 +50,10 @@ def to_s end # This method returns true if the heap is empty - # Time complexity: ? - # Space complexity: ? + # Time complexity: O(1) + # Space complexity: O(1) def empty? - raise NotImplementedError, "Method not implemented yet..." + return @store[0].nil? end private @@ -65,6 +69,8 @@ def heap_up(index) parent = (index - 1)/2 if @store[parent].key > @store[index].key swap(parent, index) + else + return end return heap_up(parent) @@ -74,7 +80,28 @@ def heap_up(index) # moves it up the heap if it's smaller # than it's parent node. def heap_down(index) - raise NotImplementedError, "Method not implemented yet..." + left_child = (index * 2) + 1 + right_child = (index * 2) + 2 + + # check for at least left + if @store[left_child] && !@store[right_child] + if @store[index].key > @store[left_child].key + swap(index, left_child) + end + end + + # checking for both + return unless @store[right_child] && @store[left_child] + + if @store[index].key > @store[left_child].key || @store[index].key > @store[right_child].key + smallest = @store[right_child].key < @store[left_child].key ? right_child : left_child + swap(index, smallest) + else + return + end + + return heap_down(index) + end # If you want a swap method... you're welcome @@ -83,4 +110,13 @@ def swap(index_1, index_2) @store[index_1] = @store[index_2] @store[index_2] = temp end -end \ No newline at end of file +end + +# heap = MinHeap.new +# p heap.add(3, "Pasta") +# p heap.add(6, "Soup") +# p heap.add(1, "Pizza") +# heap.add(0, "Donuts") +# heap.add(16, "Cookies") +# heap.add(57, "Cake") +# heap.remove \ No newline at end of file diff --git a/test/min_heap_test.rb b/test/min_heap_test.rb index 9a76c2e..186d4c2 100644 --- a/test/min_heap_test.rb +++ b/test/min_heap_test.rb @@ -51,7 +51,7 @@ expect(output).must_equal "[Donuts, Pizza, Pasta, Soup, Cookies, Cake]" end - xit "can remove nodes in the proper order" do + it "can remove nodes in the proper order" do # Arrange heap.add(3, "Pasta") heap.add(6, "Soup") From 6bc127636aa92f542ed8f4d664d08ca78cf89b4b Mon Sep 17 00:00:00 2001 From: Kareha Agesa Date: Fri, 30 Apr 2021 21:12:10 -0700 Subject: [PATCH 3/5] heapsort --- lib/heap_sort.rb | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/min_heap.rb | 27 ++++++++++------- 2 files changed, 91 insertions(+), 14 deletions(-) diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index c8a32a4..95db34f 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -1,8 +1,80 @@ +require_relative 'min_heap' +def swap(index1, index2, list) + list[index1], list[index2] = list[index2], list[index1] +end + +# for max heap +# this is helpful https://www.youtube.com/watch?v=2DmK_H7IdTo +def heap_down(start_index, end_index, list) + left_child = (start_index * 2) + 1 + right_child = (start_index * 2) + 2 + + p start_index + p left_child + p right_child + + return if left_child > end_index || right_child > end_index + + # check for at least left + if list[left_child] && !list[right_child] + if list[start_index] < list[left_child] + swap(start_index, left_child, list) + end + end + + # checking for both + return unless list[right_child] && list[left_child] + + if list[start_index] < list[left_child] || list[start_index] < list[right_child] + largest = list[right_child] > list[left_child] ? right_child : left_child + swap(start_index, largest, list) + else + return + end + + p "list in recursion: #{list}" + + return heap_down(start_index + 1, end_index, list) + +end # This method uses a heap to sort an array. # Time Complexity: ? # Space Complexity: ? -def heap_sort(list) - raise NotImplementedError, "Method not implemented yet..." -end \ No newline at end of file +def heapsort(list) + # heap = MinHeap.new() + + # until list.empty? # time: o(n) + # heap.add(list.pop) # time: o(logn) heap add, o(1) list.pop, space: o(n) + # end + + # until heap.empty? # time: ? + # list.push(heap.remove) # time: o(logn) heap remove, o(1) list.push, space: o(n) + # end + + # return list + + # turn array in max heap - bunch of heap downs + # swap 1st and last + # turn array[0..last element - 1] into max heap + # swap 1st and last + # continue + + i = 0 + j = list.length - 1 + while i < list.length - 1 + heap_down(0, j, list) + p "heap down result: #{list}" + swap(0, j, list) + j -= 1 + i += 1 + # while j < length - i - 1 + # end + p list + end + + return list +end + +p heapsort([-50, 3, 5, 16, 27]) \ No newline at end of file diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 2139c28..480383c 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -15,7 +15,7 @@ def initialize # This method adds a HeapNode instance to the heap # Time Complexity: O(logn) - # Space Complexity: ? + # Space Complexity: O(logn) def add(key, value = key) node = HeapNode.new(key, value) @store.push(node) @@ -24,8 +24,8 @@ def add(key, value = key) # This method removes and returns an element from the heap # maintaining the heap structure - # Time Complexity: ? - # Space Complexity: ? + # Time Complexity: O(logn) + # Space Complexity: O(logn) def remove() return if @store.empty? swap(0, -1) @@ -100,7 +100,7 @@ def heap_down(index) return end - return heap_down(index) + return heap_down(smallest) end @@ -113,10 +113,15 @@ def swap(index_1, index_2) end # heap = MinHeap.new -# p heap.add(3, "Pasta") -# p heap.add(6, "Soup") -# p heap.add(1, "Pizza") -# heap.add(0, "Donuts") -# heap.add(16, "Cookies") -# heap.add(57, "Cake") -# heap.remove \ No newline at end of file +# heap.add(3, 3) +# heap.add(6, 6) +# heap.add(1, 1) +# heap.add(0, 0) +# heap.add(16,16) +# heap.add(57, 57) +# p heap +# heap.remove +# p heap +# heap.remove +# heap.remove +# p heap \ No newline at end of file From bb72d2b73923b8fe60ea1490d0fbad53de9e3389 Mon Sep 17 00:00:00 2001 From: Kareha Agesa Date: Sat, 1 May 2021 22:45:09 -0700 Subject: [PATCH 4/5] fixed heap sort --- lib/heap_sort.rb | 81 ++++++++++++++++++++---------------------------- lib/min_heap.rb | 16 +--------- 2 files changed, 35 insertions(+), 62 deletions(-) diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index 95db34f..9c83fd0 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -6,42 +6,33 @@ def swap(index1, index2, list) # for max heap # this is helpful https://www.youtube.com/watch?v=2DmK_H7IdTo -def heap_down(start_index, end_index, list) - left_child = (start_index * 2) + 1 - right_child = (start_index * 2) + 2 - - p start_index - p left_child - p right_child - - return if left_child > end_index || right_child > end_index - - # check for at least left - if list[left_child] && !list[right_child] - if list[start_index] < list[left_child] - swap(start_index, left_child, list) - end +# this is also helpful: https://www.programiz.com/dsa/heap-sort +# time: o(logn) +# space: o(logn) - because of call stack? +def heap_down(list, i, length) + left_child = (i * 2) + 1 + right_child = (i * 2) + 2 + max = i + + if left_child < length && list[left_child] > list[max] + max = left_child end - - # checking for both - return unless list[right_child] && list[left_child] - if list[start_index] < list[left_child] || list[start_index] < list[right_child] - largest = list[right_child] > list[left_child] ? right_child : left_child - swap(start_index, largest, list) - else - return + if right_child < length && list[right_child] > list[max] + max = right_child end - p "list in recursion: #{list}" - - return heap_down(start_index + 1, end_index, list) - + if i != max + swap(i, max, list) + heap_down(list, max, length) + end + end + # This method uses a heap to sort an array. -# Time Complexity: ? -# Space Complexity: ? +# Time Complexity: o(nlogn) +# Space Complexity: o(logn) - bc of call stack? def heapsort(list) # heap = MinHeap.new() @@ -55,26 +46,22 @@ def heapsort(list) # return list - # turn array in max heap - bunch of heap downs - # swap 1st and last - # turn array[0..last element - 1] into max heap - # swap 1st and last - # continue + end_index = list.length - 1 + while end_index >= 0 # time: o(n) + # heapify - build a max heap + # parent nodes start at length / 2 + parent_index = end_index/2 + while parent_index >= 0 + heap_down(list, parent_index, end_index) # time: o(logn) + parent_index -= 1 + end + + # move largest element to the end + swap(0, end_index, list) - i = 0 - j = list.length - 1 - while i < list.length - 1 - heap_down(0, j, list) - p "heap down result: #{list}" - swap(0, j, list) - j -= 1 - i += 1 - # while j < length - i - 1 - # end - p list + # don't include sorted portion in further heap down + end_index -= 1 end return list end - -p heapsort([-50, 3, 5, 16, 27]) \ No newline at end of file diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 480383c..fe4b692 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -110,18 +110,4 @@ def swap(index_1, index_2) @store[index_1] = @store[index_2] @store[index_2] = temp end -end - -# heap = MinHeap.new -# heap.add(3, 3) -# heap.add(6, 6) -# heap.add(1, 1) -# heap.add(0, 0) -# heap.add(16,16) -# heap.add(57, 57) -# p heap -# heap.remove -# p heap -# heap.remove -# heap.remove -# p heap \ No newline at end of file +end \ No newline at end of file From 1481ae6256eb123946208458937bb96264b3bb63 Mon Sep 17 00:00:00 2001 From: Kareha Agesa Date: Sat, 8 May 2021 01:06:10 -0700 Subject: [PATCH 5/5] heap down cleaner way --- lib/min_heap.rb | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index fe4b692..ef9d9c3 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -83,25 +83,19 @@ def heap_down(index) left_child = (index * 2) + 1 right_child = (index * 2) + 2 - # check for at least left - if @store[left_child] && !@store[right_child] - if @store[index].key > @store[left_child].key - swap(index, left_child) - end - end - - # checking for both - return unless @store[right_child] && @store[left_child] - - if @store[index].key > @store[left_child].key || @store[index].key > @store[right_child].key - smallest = @store[right_child].key < @store[left_child].key ? right_child : left_child - swap(index, smallest) - else + # get child index + if @store[left_child] && @store[right_child] + child_index = @store[left_child].key < @store[right_child].key ? left_child : right_child + elsif @store[left_child] # no case where just right and no left + child_index = left + else # both are null so return return end - return heap_down(smallest) - + if @store[index].key > @store[child_index].key + swap(index, child_index) + return heap_down(child_index) + end end # If you want a swap method... you're welcome