RosettaCodeData/Task/Priority-queue/CoffeeScript/priority-queue-1.coffee

79 lines
1.6 KiB
CoffeeScript

PriorityQueue = ->
# Use closure style for object creation (so no "new" required).
# Private variables are toward top.
h = []
better = (a, b) ->
h[a].priority < h[b].priority
swap = (a, b) ->
[h[a], h[b]] = [h[b], h[a]]
sift_down = ->
max = h.length
n = 0
while n < max
c1 = 2*n + 1
c2 = c1 + 1
best = n
best = c1 if c1 < max and better(c1, best)
best = c2 if c2 < max and better(c2, best)
return if best == n
swap n, best
n = best
sift_up = ->
n = h.length - 1
while n > 0
parent = Math.floor((n-1) / 2)
return if better parent, n
swap n, parent
n = parent
# now return the public interface, which is an object that only
# has functions on it
self =
size: ->
h.length
push: (priority, value) ->
elem =
priority: priority
value: value
h.push elem
sift_up()
pop: ->
throw Error("cannot pop from empty queue") if h.length == 0
value = h[0].value
last = h.pop()
if h.length > 0
h[0] = last
sift_down()
value
# test
do ->
pq = PriorityQueue()
pq.push 3, "Clear drains"
pq.push 4, "Feed cat"
pq.push 5, "Make tea"
pq.push 1, "Solve RC tasks"
pq.push 2, "Tax return"
while pq.size() > 0
console.log pq.pop()
# test high performance
for n in [1..100000]
priority = Math.random()
pq.push priority, priority
v = pq.pop()
console.log "First random element was #{v}"
while pq.size() > 0
new_v = pq.pop()
throw Error "Queue broken" if new_v < v
v = new_v
console.log "Final random element was #{v}"