Last active
October 25, 2017 20:39
Binary Heap for number values (Moonscript)
This file contains 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
logE = math.log(2) | |
logB = (value) -> | |
if value == 0 do return 1 | |
return math.floor(math.log(value) / logE) | |
-- implementation of a binary minimum heap | |
-- use a function closure for instance creation | |
-- instead of tables | |
-- this yields us truly private variables and an | |
-- overall cleaner package | |
BinaryHeap = () -> | |
self = {} | |
data = {} | |
swap = (indexA, indexB) -> | |
tmp = data[indexA] | |
data[indexA] = data[indexB] | |
data[indexB] = tmp | |
lessThan = (a, b) -> | |
if a != nil and b != nil and a < b | |
return true | |
else | |
return false | |
heapUp = (index) -> | |
if index == 1 | |
return | |
parentIndex = (index - (index %2)) / 2 | |
if data[index] < data[parentIndex] | |
swap(index, parentIndex) | |
return heapUp(parentIndex) | |
heapDown = (index) -> | |
-- we should swap with the smaller child if and only if we're bigger than them | |
-- if we're not bigger we should swap with the other child if we're bigger than them | |
-- if that child is a fatty, too, we can end right here =P | |
-- also, check left first, so we properly fill up empty buckets | |
left = index * 2 | |
right = left + 1 | |
biggerThanLeft = if lessThan(data[left], data[right]) and lessThan(data[left], data[index]) then true | |
biggerThanRight = if lessThan(data[right], data[left]) and lessThan(data[right], data[index]) then true | |
if biggerThanLeft | |
swap(index, index * 2) | |
return heapDown(index * 2) | |
if biggerThanRight | |
swap(index, (index * 2) + 1) | |
return heapDown((index * 2) + 1) | |
self.store = (value) -> | |
data[#data + 1] = value | |
heapUp(#data) | |
self.retrieve = () -> | |
result = data[1] | |
data[1] = data[#data] | |
data[#data] = nil | |
heapDown(1) | |
return result | |
self.read = () -> | |
return data[1] | |
self.iterator = () -> | |
iterator = coroutine.create(() -> | |
for step = 1, #data - 1 | |
coroutine.yield(data[step]) | |
return #data) | |
return iterator | |
self.print = (width) -> | |
leafWidth = if width == nil then 4 else width | |
depth = logB(#data) | |
if #data == 0 | |
print '| (empty) |' | |
return | |
level = 0 | |
spacing = ' ' | |
while not (level > depth) | |
line = '' | |
for word = 2^level, 2^(level + 1) - 1 | |
bucketWidth = leafWidth * 2^(depth - level) | |
bucketString = if data[word] == nil then 'x' else ''..data[word] | |
for i = 1, (bucketWidth - string.len(bucketString)) | |
if i%2 == 0 | |
bucketString = spacing..bucketString | |
else | |
bucketString = bucketString..spacing | |
bucketString = string.sub(bucketString, 1, bucketWidth) | |
line ..= bucketString | |
print '|'..line..'|' | |
level = level + 1 | |
return self | |
return BinaryHeap |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment