Skip to content
17 changes: 14 additions & 3 deletions lib/heap_sort.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@


# 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)
Comment on lines +4 to 6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

raise NotImplementedError, "Method not implemented yet..."

heap = MinHeap.new

list.each do |num|
heap.add(num)
end
result = []
until heap.empty?
result << heap.remove
end
return result

end
86 changes: 70 additions & 16 deletions lib/min_heap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,32 @@ 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)
Comment on lines +17 to 19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Due to the recursion the space complexity is O(log n) due to the call stack.

raise NotImplementedError, "Method not implemented yet..."
new_element = HeapNode.new(key, value)
next_index = @store.length
@store[next_index] = new_element
heap_up(next_index)

end

# This method removes and returns an element from the heap
# maintaining the heap structure
# Time Complexity: ?
# Space Complexity: ?
# maintaining the heap structure
# Time Complexity: O(log(n))
# Space Complexity: O(1)
def remove()
Comment on lines +28 to 31

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Due to the recursion the space complexity is O(log n) due to the call stack.

raise NotImplementedError, "Method not implemented yet..."
return if @store.empty?

last_index = @store.length - 1
swap(0, last_index)

temp = @store[last_index]
@store.delete_at(last_index)
heap_down(0)

return temp.value

end


Expand All @@ -39,33 +53,73 @@ def to_s
end

output += @store.last.value + "]"

return output
end

# This method returns true if the heap is empty
# Time complexity: ?
# Space complexity: ?
# Time complexity: O(1)
# Space complexity: O(1)
def empty?
Comment on lines +61 to 63

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

raise NotImplementedError, "Method not implemented yet..."
return @store.length == 0
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)
Comment on lines +74 to 76

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Due to the recursion the space complexity is O(log n) due to the call stack.


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].key < @store[parent_index].key
swap(index, parent_index)
heap_up(parent_index)
else
return
end

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.
# Time complexity: O(log(n))
# Space complexity: O(1)
def heap_down(index)
Comment on lines +97 to 99

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Due to the recursion the space complexity is O(log n) due to the call stack.

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

return if left_child_idx > last_index # if we reach the end of/edge of the tree return

# 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)
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

end

# If you want a swap method... you're welcome
Expand Down
12 changes: 6 additions & 6 deletions test/heapsort_test.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require_relative "test_helper"

xdescribe "heapsort" do
describe "heapsort" do
it "sorts an empty array" do
# Arrange
# Arrange
list = []

# Act
Expand All @@ -13,7 +13,7 @@
end

it "can sort a 1-element array" do
# Arrange
# Arrange
list = [5]

# Act
Expand All @@ -22,15 +22,15 @@
# Assert
expect(result).must_equal [5]
end

it "can sort a 5-element array" do
# Arrange
# Arrange
list = [5, 27, 3, 16, -50]

# Act
result = heapsort(list)

# Assert
expect(result).must_equal [-50, 3, 5, 16, 27]
end
end
end