79 lines
1.6 KiB
CoffeeScript
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}"
|