Last active
October 3, 2022 13:54
-
-
Save sepastian/e72a24fa13d1cbf63c8725772ad1d0e9 to your computer and use it in GitHub Desktop.
Heap in Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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