class PriorityHeap
A priority queue implementation using a standard binary minheap. It uses straight comparison of its contents to determine priority. See https://en.wikipedia.org/wiki/Binary_heap for explanations of the main methods.
Definitions
def initialize
Initializes the heap.
Implementation
def initialize
# The heap is represented with an array containing a binary tree. See
# https://en.wikipedia.org/wiki/Binary_heap#Heap_implementation for how this array
# is built up.
@contents = []
end
def peek
Signature
-
returns
Object | Nil
the smallest element in the heap without removing it, or nil if the heap is empty.
Implementation
def peek
@contents[0]
end
def size
Signature
-
returns
Integer
the number of elements in the heap.
Implementation
def size
@contents.size
end
def pop
Removes and returns the smallest element in the heap, or nil if the heap is empty.
Signature
-
returns
Object | Nil
The smallest element in the heap, or nil if the heap is empty.
Implementation
def pop
# If the heap is empty:
if @contents.empty?
return nil
end
# If we have only one item, no swapping is required:
if @contents.size == 1
return @contents.pop
end
# Take the root of the tree:
value = @contents[0]
# Remove the last item in the tree:
last = @contents.pop
# Overwrite the root of the tree with the item:
@contents[0] = last
# Bubble it down into place:
bubble_down(0)
# validate!
return value
end
def push(element)
Add a new element to the heap, then rearrange elements until the heap invariant is true again.
Signature
-
parameter
element
Object
The element to add to the heap.
Implementation
def push(element)
# Insert the item at the end of the heap:
@contents.push(element)
# Bubble it up into position:
bubble_up(@contents.size - 1)
# validate!
return self
end
def clear!
Empties out the heap, discarding all elements
Implementation
def clear!
@contents = []
end
def valid?
Validate the heap invariant. Every element except the root must not be smaller than its parent element. Note that it MAY be equal.
Implementation
def valid?
# Notice we skip index 0 on purpose, because it has no parent
(1..(@contents.size - 1)).all? { |e| @contents[e] >= @contents[(e - 1) / 2] }
end