Last active
October 25, 2017 20:39
-
-
Save vyo/4c59c9ed8c6516a4ee0609a3bc801fb6 to your computer and use it in GitHub Desktop.
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