Class: DataStructuresRMolinari::Heap
- Inherits:
-
Object
- Object
- DataStructuresRMolinari::Heap
- Includes:
- Shared, Shared::BinaryTreeArithmetic
- Defined in:
- lib/data_structures_rmolinari/heap.rb
Overview
-
let caller see the priority of the top element. Maybe this is useful sometimes.
A heap is a balanced binary tree in which each entry has an associated priority. For each node p of the tree that isn’t the root, the priority of the element at p is not less than the priority of the element at the parent of p.
Thus the priority at each node p - root or not - is no greater than the priorities of the elements in the subtree rooted at p. It is a “min-heap”.
We can make it a max-heap, in which each node’s priority is no greater than the priority of its parent, via a parameter to the initializer.
We provide the following operations
-
empty?-
is the heap empty?
-
O(1)
-
-
insert(item, priority)
-
add a new item to the heap with an associated priority
-
O(log N)
-
-
top-
return the lowest-priority element, which is the element at the root of the tree. In a max-heap this is the highest-priority element.
-
O(1)
-
-
pop-
removes and returns the item that would be returned by
top -
O(log N)
-
-
update(item, priority)
-
tell the heap that the priority of a particular item has changed
-
O(log N)
-
Here N is the number of elements in the heap.
The internal requirements needed to implement update have several consequences.
-
Items added to the heap must be distinct. Otherwise we would not know which occurrence to update
-
There is some bookkeeping overhead.
If client code doesn’t need to call update then we can create a “non-addressable” heap that allows for the insertion of duplicate items and has slightly faster runtime overall. See the arguments to the initializer.
References:
-
Edelkamp, S., Elmasry, A., Katajainen, J., _Optimizing Binary Heaps_, Theory Comput Syst (2017), vol 61, pp 606-636, DOI 10.1007/s00224-017-9760-2
Constant Summary
Constants included from Shared
Instance Attribute Summary collapse
-
#size ⇒ Object
readonly
The number of items currently in the heap.
Instance Method Summary collapse
-
#empty? ⇒ Boolean
Is the heap empty?.
-
#initialize(max_heap: false, addressable: true, debug: false) ⇒ Heap
constructor
A new instance of Heap.
-
#insert(value, priority) ⇒ Object
Insert a new element into the heap with the given priority.
-
#pop ⇒ Object
Return the top of the heap and remove it, updating the structure to maintain the necessary properties.
-
#top ⇒ Object
Return the top of the heap without removing it.
-
#update(element, priority) ⇒ Object
Update the priority of the given element and maintain the necessary heap properties.
Methods included from Shared
Constructor Details
#initialize(max_heap: false, addressable: true, debug: false) ⇒ Heap
Returns a new instance of Heap.
64 65 66 67 68 69 70 71 |
# File 'lib/data_structures_rmolinari/heap.rb', line 64 def initialize(max_heap: false, addressable: true, debug: false) @data = [] @size = 0 @max_heap = max_heap @addressable = addressable @index_of = {} # used in addressable heaps @debug = debug end |
Instance Attribute Details
#size ⇒ Object (readonly)
The number of items currently in the heap
51 52 53 |
# File 'lib/data_structures_rmolinari/heap.rb', line 51 def size @size end |
Instance Method Details
#empty? ⇒ Boolean
Is the heap empty?
74 75 76 |
# File 'lib/data_structures_rmolinari/heap.rb', line 74 def empty? @size.zero? end |
#insert(value, priority) ⇒ Object
Insert a new element into the heap with the given priority.
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/data_structures_rmolinari/heap.rb', line 82 def insert(value, priority) raise DataError, "Heap already contains #{value}" if @addressable && contains?(value) @size += 1 d = InternalPair.new(value, priority) assign(d, @size) sift_up(@size) end |
#pop ⇒ Object
Return the top of the heap and remove it, updating the structure to maintain the necessary properties.
105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/data_structures_rmolinari/heap.rb', line 105 def pop result = top assign(@data[@size], root) @data[@size] = nil @size -= 1 @index_of.delete(result) if @addressable sift_down(root) if @size.positive? result end |
#top ⇒ Object
Return the top of the heap without removing it
97 98 99 100 101 |
# File 'lib/data_structures_rmolinari/heap.rb', line 97 def top raise 'Heap is empty!' unless @size.positive? @data[root].item end |
#update(element, priority) ⇒ Object
Update the priority of the given element and maintain the necessary heap properties.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/data_structures_rmolinari/heap.rb', line 123 def update(element, priority) raise LogicError, 'Cannot update priorities in a non-addressable heap' unless @addressable raise DataError, "Cannot update priority for value #{element} not already in the heap" unless contains?(element) idx = @index_of[element] old = @data[idx].priority @data[idx].priority = priority if less_than_priority?(old, priority) sift_down(idx) elsif less_than_priority?(priority, old) sift_up(idx) end check_heap_property if @debug end |