mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-02-09 08:46:19 +01:00
Merge pull request #195 from aparibocci/master
Adding max-heap implementation + unit tests
This commit is contained in:
commit
9621fec9c8
2 changed files with 133 additions and 0 deletions
87
data_structures/heaps/max_heap.rb
Normal file
87
data_structures/heaps/max_heap.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
##
|
||||
# This class represents an array-backed max-heap.
|
||||
|
||||
class MaxHeap
|
||||
|
||||
attr_reader :arr
|
||||
attr_accessor :heap_size
|
||||
|
||||
##
|
||||
# Creates a new max-heap using the provided collection of initial values, if provided (empty by default).
|
||||
# Note: a clone of the input collection is created to avoid alterations to the input.
|
||||
|
||||
def initialize(elements = [])
|
||||
@arr = [0] + elements.map(&:clone)
|
||||
@heap_size = arr.size - 1
|
||||
for i in ((arr.size / 2).floor).downto 1
|
||||
max_heapify(i)
|
||||
end
|
||||
end
|
||||
|
||||
def to_array
|
||||
return arr[1..heap_size].map(&:clone)
|
||||
end
|
||||
|
||||
def empty?
|
||||
return heap_size == 0
|
||||
end
|
||||
|
||||
def max
|
||||
return nil if empty?
|
||||
return @arr[1]
|
||||
end
|
||||
|
||||
def extract_max
|
||||
return nil if empty?
|
||||
m = max
|
||||
@arr[1] = @arr[heap_size]
|
||||
@heap_size -= 1
|
||||
max_heapify(1)
|
||||
return m
|
||||
end
|
||||
|
||||
def insert(k)
|
||||
@heap_size += 1
|
||||
@arr[heap_size] = -Float::INFINITY
|
||||
increase_to(heap_size, k)
|
||||
end
|
||||
|
||||
private
|
||||
def max_heapify(i)
|
||||
l = left(i)
|
||||
r = right(i)
|
||||
m = i
|
||||
if l <= heap_size && arr[l] > arr[i]
|
||||
m = l
|
||||
end
|
||||
if r <= heap_size && arr[r] > arr[m]
|
||||
m = r
|
||||
end
|
||||
if m != i
|
||||
arr[i], arr[m] = arr[m], arr[i]
|
||||
max_heapify(m)
|
||||
end
|
||||
end
|
||||
|
||||
def increase_to(i, k)
|
||||
raise ArgumentError.new('MaxHeap#increase_to does not support lower values for the key') if arr[i] > k
|
||||
@arr[i] = k
|
||||
j = i
|
||||
while parent(j) > 0 && arr[parent(j)] < arr[j]
|
||||
arr[j], arr[parent(j)] = arr[parent(j)], arr[j]
|
||||
j = parent(j)
|
||||
end
|
||||
end
|
||||
|
||||
def parent(i)
|
||||
return (i / 2).floor
|
||||
end
|
||||
|
||||
def left(i)
|
||||
return 2*i
|
||||
end
|
||||
|
||||
def right(i)
|
||||
return 2*i + 1
|
||||
end
|
||||
end
|
46
data_structures/heaps/max_heap_test.rb
Normal file
46
data_structures/heaps/max_heap_test.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
require 'minitest/autorun'
|
||||
require_relative 'max_heap'
|
||||
|
||||
class TestMaxHeap < Minitest::Test
|
||||
def test_to_array_returns_array_representation
|
||||
heap = MaxHeap.new([4, 1, 3, 3, 16, 9, 10, 14, 8, 7])
|
||||
assert heap.to_array == [16, 14, 10, 8, 7, 9, 3, 3, 4, 1]
|
||||
end
|
||||
|
||||
def test_empty_returns_true_for_empty_heap
|
||||
heap = MaxHeap.new
|
||||
assert heap.empty?
|
||||
end
|
||||
|
||||
def test_empty_returns_false_for_non_empty_heap
|
||||
heap = MaxHeap.new([1])
|
||||
assert !heap.empty?
|
||||
end
|
||||
|
||||
def test_max_returns_maximum_heap_element
|
||||
heap = MaxHeap.new([4, 1, 3])
|
||||
assert heap.max == 4
|
||||
end
|
||||
|
||||
def test_max_returns_nil_if_empty_heap
|
||||
heap = MaxHeap.new
|
||||
assert heap.max.nil?
|
||||
end
|
||||
|
||||
def test_extract_max_returns_and_removes_maximum_heap_element
|
||||
heap = MaxHeap.new([4, 1, 3])
|
||||
assert heap.extract_max == 4
|
||||
assert heap.to_array == [3, 1]
|
||||
end
|
||||
|
||||
def test_extract_max_returns_nil_if_empty_heap
|
||||
heap = MaxHeap.new
|
||||
assert heap.extract_max.nil?
|
||||
end
|
||||
|
||||
def test_insert_adds_element_to_appropriate_position
|
||||
heap = MaxHeap.new([4, 1, 3])
|
||||
heap.insert(2)
|
||||
assert heap.to_array == [4, 2, 3, 1]
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue