From fe8607d3a309828dced30b1dd49070d7afbda135 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 00:23:22 -0700 Subject: [PATCH 01/16] add min_heap methods --- lib/min_heap.rb | 51 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 6eaa630..bade925 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -17,15 +17,25 @@ def initialize # Time Complexity: ? # Space Complexity: ? def add(key, value = key) - raise NotImplementedError, "Method not implemented yet..." + new_element = HeapNode.new(key, value) + next_index = @store.length + @store[next_index] = new_element + end # This method removes and returns an element from the heap - # maintaining the heap structure + # maintaining the heap structure # Time Complexity: ? # Space Complexity: ? def remove() - raise NotImplementedError, "Method not implemented yet..." + return if @store.empty? + + last_index = @store.length -1 + temp = @store[last_index] + @store.delete_at(last_index) + + return temp + end @@ -47,7 +57,7 @@ def to_s # Time complexity: ? # Space complexity: ? def empty? - raise NotImplementedError, "Method not implemented yet..." + return @store.length == 0 end private @@ -58,14 +68,43 @@ def empty? # Time complexity: ? # Space complexity: ? def heap_up(index) - + return if index == 0 # if index is 0 it means its a parent so no need to perform heap up + + if index % 2 == 0 # if index is even number it means its a right chile as right_child = 2*(i) + 2 <-- and this is always even number + parent_index = (index - 2) / 2 + else + parent_index = (index - 1) / 2 + end + + if @store[index] < @store[parent_index] + swap(index, parent_index) + heap_up(parent_index) + else + return + end + end # This helper method takes an index and # moves it up the heap if it's smaller # than it's parent node. def heap_down(index) - raise NotImplementedError, "Method not implemented yet..." + return if @store.empty? + last_index = @store.length -1 + return if index == last_index # if index is the last one, we have reached the right most node + + + right_child_idx = (2 * index) + 2 + left_child_idx = (2 * index) + 1 + + if left_child_idx == last_index + swap(left_child_idx, index) + else + swap(right_child_idx, index) + end + + heap_down(right_child_idx) + end # If you want a swap method... you're welcome From 4fa6eaef9f44381291314172acae26ce2fef49c0 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 18:30:50 -0700 Subject: [PATCH 02/16] updated heap_up method --- lib/min_heap.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index bade925..cf1202e 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -35,7 +35,7 @@ def remove() @store.delete_at(last_index) return temp - + end @@ -76,7 +76,7 @@ def heap_up(index) parent_index = (index - 1) / 2 end - if @store[index] < @store[parent_index] + if @store[index].key < @store[parent_index].key swap(index, parent_index) heap_up(parent_index) else From a3ae999ae2a5b827013335be4e990fd0d32a2a50 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 18:47:44 -0700 Subject: [PATCH 03/16] updated add method --- lib/min_heap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index cf1202e..c751fdd 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -20,6 +20,7 @@ def add(key, value = key) new_element = HeapNode.new(key, value) next_index = @store.length @store[next_index] = new_element + heap_up(next_index) end From 6fe2859ddc5519332715b0971de6de8029160a12 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 19:02:01 -0700 Subject: [PATCH 04/16] updated remove method --- lib/min_heap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index c751fdd..f65feb6 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -30,6 +30,7 @@ def add(key, value = key) # Space Complexity: ? def remove() return if @store.empty? + heap_down(0) # 0 would be the root last_index = @store.length -1 temp = @store[last_index] From 18b36765f8a569efb8afab8260b8fe2ade528b90 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 19:28:20 -0700 Subject: [PATCH 05/16] updated remove method --- lib/min_heap.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index f65feb6..5b846a2 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -32,11 +32,11 @@ def remove() return if @store.empty? heap_down(0) # 0 would be the root - last_index = @store.length -1 + last_index = @store.length - 1 temp = @store[last_index] @store.delete_at(last_index) - return temp + return temp.value end @@ -92,7 +92,7 @@ def heap_up(index) # than it's parent node. def heap_down(index) return if @store.empty? - last_index = @store.length -1 + last_index = @store.length - 1 return if index == last_index # if index is the last one, we have reached the right most node From e8975f68ad80e5e527be521972107775a4ee5919 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 19:41:18 -0700 Subject: [PATCH 06/16] update heap_down method --- lib/min_heap.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 5b846a2..edc9c11 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -101,12 +101,12 @@ def heap_down(index) if left_child_idx == last_index swap(left_child_idx, index) + heap_down(left_child_idx) else swap(right_child_idx, index) + heap_down(right_child_idx) end - heap_down(right_child_idx) - end # If you want a swap method... you're welcome From 605961a66c16c6d630415fa71b02e542ac5a745a Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 19:55:01 -0700 Subject: [PATCH 07/16] update remove method --- lib/min_heap.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index edc9c11..23cfd40 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -30,11 +30,13 @@ def add(key, value = key) # Space Complexity: ? def remove() return if @store.empty? - heap_down(0) # 0 would be the root - + last_index = @store.length - 1 + swap(0, last_index) + temp = @store[last_index] @store.delete_at(last_index) + heap_down(0) return temp.value From 749713e5e97e2e675090e73f8e604fd95bd474d4 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 20:07:49 -0700 Subject: [PATCH 08/16] updated heap_down method --- lib/min_heap.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 23cfd40..3f2ce4b 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -101,12 +101,15 @@ def heap_down(index) right_child_idx = (2 * index) + 2 left_child_idx = (2 * index) + 1 - if left_child_idx == last_index + if @store[index].key > @store[right_child_idx] + swap(right_child_idx, index) # swap only when value is greater than child + heap_down(right_child_idx) + elsif + @store[index].key > @store[left_child_idx] swap(left_child_idx, index) heap_down(left_child_idx) else - swap(right_child_idx, index) - heap_down(right_child_idx) + return end end From d988a5456392313ea4fa109ceebd2c599a219e0b Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Wed, 30 Sep 2020 20:16:31 -0700 Subject: [PATCH 09/16] minor changes --- lib/min_heap.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 3f2ce4b..f738c88 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -101,11 +101,14 @@ def heap_down(index) right_child_idx = (2 * index) + 2 left_child_idx = (2 * index) + 1 - if @store[index].key > @store[right_child_idx] + return if right_child_idx > last_index + return if left_child_idx > last_index + + if @store[index].key > @store[right_child_idx].key swap(right_child_idx, index) # swap only when value is greater than child heap_down(right_child_idx) elsif - @store[index].key > @store[left_child_idx] + @store[index].key > @store[left_child_idx].key swap(left_child_idx, index) heap_down(left_child_idx) else From f298e87657a01055223092a02babb9d4a6070fcd Mon Sep 17 00:00:00 2001 From: Haben Date: Thu, 1 Oct 2020 20:45:48 -0700 Subject: [PATCH 10/16] last update heap_down method --- lib/min_heap.rb | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index f738c88..8ca521c 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -18,7 +18,7 @@ def initialize # Space Complexity: ? def add(key, value = key) new_element = HeapNode.new(key, value) - next_index = @store.length + next_index = @store.length @store[next_index] = new_element heap_up(next_index) @@ -30,7 +30,7 @@ def add(key, value = key) # Space Complexity: ? def remove() return if @store.empty? - + last_index = @store.length - 1 swap(0, last_index) @@ -39,7 +39,7 @@ def remove() heap_down(0) return temp.value - + end @@ -53,7 +53,7 @@ def to_s end output += @store.last.value + "]" - + return output end @@ -89,26 +89,25 @@ def heap_up(index) end - # This helper method takes an index and + # This helper method takes an index and # moves it up the heap if it's smaller # than it's parent node. def heap_down(index) return if @store.empty? last_index = @store.length - 1 return if index == last_index # if index is the last one, we have reached the right most node - - + + right_child_idx = (2 * index) + 2 left_child_idx = (2 * index) + 1 - return if right_child_idx > last_index + return if right_child_idx > last_index return if left_child_idx > last_index - if @store[index].key > @store[right_child_idx].key + if @store[index].key > @store[right_child_idx].key && @store[right_child_idx].key < @store[left_child_idx].key swap(right_child_idx, index) # swap only when value is greater than child heap_down(right_child_idx) - elsif - @store[index].key > @store[left_child_idx].key + elsif @store[index].key > @store[left_child_idx].key swap(left_child_idx, index) heap_down(left_child_idx) else From 1146adfa787fa51f68abca1ac46898d82c9154c8 Mon Sep 17 00:00:00 2001 From: Haben Date: Thu, 1 Oct 2020 22:31:27 -0700 Subject: [PATCH 11/16] added heapsort method --- lib/heap_sort.rb | 9 ++++++++- lib/min_heap.rb | 10 ++++++++++ test/heapsort_test.rb | 12 ++++++------ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index 6b692e4..9df556e 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -4,5 +4,12 @@ # Time Complexity: ? # Space Complexity: ? def heapsort(list) - raise NotImplementedError, "Method not implemented yet..." + + heap = MinHeap.new + + list.each do |num| + heap.add(num) + end + return heap.to_array + end \ No newline at end of file diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 8ca521c..48fd32b 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -64,6 +64,16 @@ def empty? return @store.length == 0 end + # helper method for heapsort + def to_array + output = [] + (@store.length).times do |index| + output << @store[index].value + end + return output + + end + private # This helper method takes an index and diff --git a/test/heapsort_test.rb b/test/heapsort_test.rb index 34402ac..fb7fa84 100644 --- a/test/heapsort_test.rb +++ b/test/heapsort_test.rb @@ -1,8 +1,8 @@ require_relative "test_helper" -xdescribe "heapsort" do +describe "heapsort" do it "sorts an empty array" do - # Arrange + # Arrange list = [] # Act @@ -13,7 +13,7 @@ end it "can sort a 1-element array" do - # Arrange + # Arrange list = [5] # Act @@ -22,9 +22,9 @@ # Assert expect(result).must_equal [5] end - + it "can sort a 5-element array" do - # Arrange + # Arrange list = [5, 27, 3, 16, -50] # Act @@ -32,5 +32,5 @@ # Assert expect(result).must_equal [-50, 3, 5, 16, 27] - end + end end \ No newline at end of file From b24506b638d818172df304849d3653dd89f5a312 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Thu, 1 Oct 2020 22:50:08 -0700 Subject: [PATCH 12/16] updated heapsort --- lib/heap_sort.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index 9df556e..c351a0f 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -10,6 +10,10 @@ def heapsort(list) list.each do |num| heap.add(num) end - return heap.to_array + result = [] + until heap.empty? + result << heap.remove + end + return result end \ No newline at end of file From a1ad99263f7e2a5f00d2f4b429b22fa8996e4fee Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Thu, 1 Oct 2020 23:08:59 -0700 Subject: [PATCH 13/16] updated the remove method logic --- lib/min_heap.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 48fd32b..cfcd92e 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -114,16 +114,29 @@ def heap_down(index) return if right_child_idx > last_index return if left_child_idx > last_index - if @store[index].key > @store[right_child_idx].key && @store[right_child_idx].key < @store[left_child_idx].key - swap(right_child_idx, index) # swap only when value is greater than child - heap_down(right_child_idx) - elsif @store[index].key > @store[left_child_idx].key - swap(left_child_idx, index) - heap_down(left_child_idx) + if @store[index].key > @store[right_child_idx].key || @store[index].key > @store[left_child_idx].key + if @store[right_child_idx].key < @store[left_child_idx].key + swap(right_child_idx, index) # swap only when value is greater than child + heap_down(right_child_idx) + else + swap(left_child_idx, index) # swap only when value is greater than child + heap_down(left_child_idx) + end else return end + + ##if @store[index].key > @store[right_child_idx].key && @store[right_child_idx].key < @store[left_child_idx].key + ## swap(right_child_idx, index) # swap only when value is greater than child + ## heap_down(right_child_idx) + ## elsif @store[index].key > @store[left_child_idx].key + ## swap(left_child_idx, index) + ## heap_down(left_child_idx) + ##else + ## return + ##end + end # If you want a swap method... you're welcome From c1a0b818b696fc45aba1e12a61b5f18027e092ce Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Thu, 1 Oct 2020 23:20:39 -0700 Subject: [PATCH 14/16] fixed remove logic --- lib/min_heap.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index cfcd92e..648f843 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -111,11 +111,13 @@ def heap_down(index) right_child_idx = (2 * index) + 2 left_child_idx = (2 * index) + 1 - return if right_child_idx > last_index + ##return if right_child_idx > last_index return if left_child_idx > last_index - if @store[index].key > @store[right_child_idx].key || @store[index].key > @store[left_child_idx].key - if @store[right_child_idx].key < @store[left_child_idx].key + if right_child_idx > last_index + + if (right_child_idx <= last_index && @store[index].key > @store[right_child_idx].key) || @store[index].key > @store[left_child_idx].key + if (right_child_idx <= last_index && @store[right_child_idx].key < @store[left_child_idx].key) swap(right_child_idx, index) # swap only when value is greater than child heap_down(right_child_idx) else From 9357fc6794332e4f995f8daa88dae9c5b7da527e Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Thu, 1 Oct 2020 23:30:48 -0700 Subject: [PATCH 15/16] removed commented code --- lib/min_heap.rb | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 648f843..654a623 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -107,15 +107,13 @@ def heap_down(index) last_index = @store.length - 1 return if index == last_index # if index is the last one, we have reached the right most node - right_child_idx = (2 * index) + 2 left_child_idx = (2 * index) + 1 - ##return if right_child_idx > last_index - return if left_child_idx > last_index - - if right_child_idx > last_index + return if left_child_idx > last_index # if we reach the end of/edge of the tree return + # if the current parent is greater than either of the child nodes then find the smallest of the two childs and swap it with the parent + # only check the reight child if the right_child_index is less than the max valid index of the array. if (right_child_idx <= last_index && @store[index].key > @store[right_child_idx].key) || @store[index].key > @store[left_child_idx].key if (right_child_idx <= last_index && @store[right_child_idx].key < @store[left_child_idx].key) swap(right_child_idx, index) # swap only when value is greater than child @@ -128,17 +126,6 @@ def heap_down(index) return end - - ##if @store[index].key > @store[right_child_idx].key && @store[right_child_idx].key < @store[left_child_idx].key - ## swap(right_child_idx, index) # swap only when value is greater than child - ## heap_down(right_child_idx) - ## elsif @store[index].key > @store[left_child_idx].key - ## swap(left_child_idx, index) - ## heap_down(left_child_idx) - ##else - ## return - ##end - end # If you want a swap method... you're welcome From e08052c9bcf31d97a7d32d88bc36ffd080652e62 Mon Sep 17 00:00:00 2001 From: "Haben Foto (Third Sector New England Inc)" Date: Thu, 1 Oct 2020 23:59:01 -0700 Subject: [PATCH 16/16] added time & space complexity --- lib/heap_sort.rb | 4 ++-- lib/min_heap.rb | 28 +++++++++++----------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index c351a0f..99b921d 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -1,8 +1,8 @@ # This method uses a heap to sort an array. -# Time Complexity: ? -# Space Complexity: ? +# Time Complexity: O(n log(n)) +# Space Complexity: O(n) def heapsort(list) heap = MinHeap.new diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 654a623..32bbd90 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -14,8 +14,8 @@ def initialize end # This method adds a HeapNode instance to the heap - # Time Complexity: ? - # Space Complexity: ? + # Time Complexity: O(log(n)) + # Space Complexity: O(1) def add(key, value = key) new_element = HeapNode.new(key, value) next_index = @store.length @@ -26,8 +26,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(log(n)) + # Space Complexity: O(1) def remove() return if @store.empty? @@ -58,29 +58,21 @@ 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? return @store.length == 0 end - # helper method for heapsort - def to_array - output = [] - (@store.length).times do |index| - output << @store[index].value - end - return output - end private # 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(log(n)) + # Space complexity: O(1) def heap_up(index) return if index == 0 # if index is 0 it means its a parent so no need to perform heap up @@ -102,6 +94,8 @@ def heap_up(index) # This helper method takes an index and # moves it up the heap if it's smaller # than it's parent node. + # Time complexity: O(log(n)) + # Space complexity: O(1) def heap_down(index) return if @store.empty? last_index = @store.length - 1 @@ -112,7 +106,7 @@ def heap_down(index) return if left_child_idx > last_index # if we reach the end of/edge of the tree return - # if the current parent is greater than either of the child nodes then find the smallest of the two childs and swap it with the parent + # only swap when current parent is greater than either of the child nodes then find the smallest of the two dscendants # only check the reight child if the right_child_index is less than the max valid index of the array. if (right_child_idx <= last_index && @store[index].key > @store[right_child_idx].key) || @store[index].key > @store[left_child_idx].key if (right_child_idx <= last_index && @store[right_child_idx].key < @store[left_child_idx].key)