Skip to content

Instantly share code, notes, and snippets.

@sepastian
Last active October 3, 2022 13:54
Show Gist options
  • Save sepastian/e72a24fa13d1cbf63c8725772ad1d0e9 to your computer and use it in GitHub Desktop.
Save sepastian/e72a24fa13d1cbf63c8725772ad1d0e9 to your computer and use it in GitHub Desktop.
Heap in Ruby
class Heap
def initialize(*elems)
@h= heapify(elems)
end
def inspect
return '(empty)' if @h.empty?
@h
.group_by.with_index{ Math.log2(_2+1).to_i }
.map{ |l,vs| vs.join(' ') }
.join("\n")
end
def insert(v)
# Place new value at the end,
# then bubble up.
@h << v
return if @h.size == 1
i, ip= @h.size-1, parent(@h.size-1)
n, p= @h[i], @h[ip]
return if i == 0
while n > p
@h[i], @h[ip]= @h[ip], @h[i]
i, ip= ip, parent(ip)
break if ip.nil?
n, p= @h[i], @h[ip]
end
end
def remove()
# Remove first element;
# move last element to root;
# bubble down root.
return @h.delete_at(0) if @h.size == 1
res= @h.first
@h[0]= @h.delete_at(@h.size- 1)
i, il, ir= 0, left(0), right(0)
n, l, r= @h[i], @h[il], @h[ir]
while n < (l||n) || n < (r||n)
j= l >= (r||l) ? il : ir
@h[i], @h[j]= @h[j], @h[i]
i, il, ir= j, left(j), right(j)
n, l, r= @h[i], @h[il], @h[ir]
end
res
end
def size()
@h.size
end
private
def heapify(elems)
h= elems
i= (h.size-2)/2
il, ir= left(i), right(i)
n, l, r= h[i], h[il], h[ir]
while i >= 0
while n < (l||n) || n < (r||n)
# bubble down: swap node with larger child
# until heap condition is met
j= l >= (r||l) ? il : ir
h[i], h[j] = h[j], h[i]
i, il, ir= j, left(j), right(j)
n, l, r= h[i], h[il], h[ir]
end
# continue with next node, to the left/upwards
i, il, ir= i-1, left(i-1), right(i-1)
n, l, r= h[i], h[il], h[ir]
end
h
end
def parent(i)
return nil if i == 0
((i-1)/2).to_i
end
def left(i)
i*2+1
end
def right(i)
i*2+2
end
end
#####
def sep()
puts '-'* 10
end
h= Heap.new(1,2,3,5,6,7,8)
p h
sep
h.insert(10)
p h
sep
puts h.remove()
p h
sep
elems= h.size.times.map{ h.remove() }
p h
p elems
sep
10.times
.map{ rand(20) }
.each{ h.insert(_1) }
p h
sep
h= Heap.new("a", "b", "c", "x")
p h
sep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment