core :: MinHeap :: defaultinit
# A min-heap implemented over an array
#
# The order is given by the `comparator`.
#
# ~~~
# var a = [3,4,1,2]
# var h = new MinHeap[Int].default
# h.add_all(a)
# assert h.peek == 1
# var b = h.take_all
# assert b == [1, 2, 3, 4]
# ~~~
class MinHeap[E: Object]
super Queue[E]
private var items = new Array[E]
# The comparator used to order the Heap
var comparator: Comparator
# Use the `default_comparator` on Comparable elements
#
# Require self isa MinHeap[Comparable]
init default
do
assert self isa MinHeap[Comparable]
init(default_comparator)
end
redef fun is_empty do return items.is_empty
redef fun length do return items.length
redef fun iterator do return items.iterator
redef fun clear do items.clear
redef fun peek do return items.first
redef fun add(e)
do
#assert assert_best else print "try to add {e}"
#var ol = length
var ei = items.length + 1
while ei > 1 do
var pi = ei/2
var p = items[pi-1]
if comparator.compare(p, e) <= 0 then break
# bubble-up
items[ei-1] = p
# next
ei = pi
end
items[ei-1] = e
#assert length == ol + 1
#assert assert_best else print "added {e}"
end
redef fun take do
#assert assert_best else print "tri to take"
#var ol = length
if length < 2 then return items.pop
var res = items.first
var ei = 1
var e = items.pop
var last = items.length
loop
# Check first child
var ci = ei*2
if ci > last then break # no children
var c = items[ci-1]
var upc = comparator.compare(e, c) > 0
# Check second child
var c2i = ci + 1
if c2i <= last then do
var c2 = items[c2i-1]
# possibility to bubble-down to c2, or not?
if comparator.compare(e, c2) <= 0 then break label
# c2 is a better path, or not?
if upc and comparator.compare(c2, c) > 0 then break label
# goes to c2 path
upc = true
c = c2
ci = c2i
end label
# bubble-down?
if not upc then break
items[ei-1] = c
ei = ci
end
items[ei-1] = e
#assert length == ol - 1 else print "is {length}, expected {ol - 1}"
#assert assert_best else print "dequed {res}"
return res
end
# Used internally do debug the Heap.
# Not removed because this can still be useful.
private fun assert_best: Bool
do
if is_empty then return true
var b = peek
for i in self do if comparator.compare(b, i) > 0 then
#print " peek is {b} but better found {i}"
for j in self do
#print " {j}"
end
return false
end
return true
end
end
lib/core/queue.nit:209,1--323,3