Class: Philiprehberger::PriorityQueue::Queue
- Inherits:
-
Object
- Object
- Philiprehberger::PriorityQueue::Queue
- Includes:
- Enumerable
- Defined in:
- lib/philiprehberger/priority_queue.rb
Instance Attribute Summary collapse
-
#size ⇒ Object
readonly
Returns the value of attribute size.
Instance Method Summary collapse
- #<<(item_with_priority) ⇒ Object
- #change_priority(item, new_priority) ⇒ Object
- #clear ⇒ Object
- #delete(item) ⇒ Object
- #drain ⇒ Object
- #each(&block) ⇒ Object
- #empty? ⇒ Boolean
- #include?(item) ⇒ Boolean
-
#initialize(mode: :min, &comparator) ⇒ Queue
constructor
A new instance of Queue.
- #merge(other) ⇒ Object
- #peek ⇒ Object
- #peek_priority ⇒ Object
- #pop ⇒ Object
- #priorities ⇒ Object
- #push(item, priority:) ⇒ Object
- #push_many(items) ⇒ Object
- #to_a ⇒ Object
Constructor Details
#initialize(mode: :min, &comparator) ⇒ Queue
Returns a new instance of Queue.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/philiprehberger/priority_queue.rb', line 12 def initialize(mode: :min, &comparator) @heap = [] @size = 0 @insertion_counter = 0 @item_index = {} @comparator = if comparator comparator elsif mode == :max ->(a, b) { b <=> a } else ->(a, b) { a <=> b } end end |
Instance Attribute Details
#size ⇒ Object (readonly)
Returns the value of attribute size.
10 11 12 |
# File 'lib/philiprehberger/priority_queue.rb', line 10 def size @size end |
Instance Method Details
#<<(item_with_priority) ⇒ Object
37 38 39 40 41 |
# File 'lib/philiprehberger/priority_queue.rb', line 37 def <<(item_with_priority) raise ArgumentError, 'Expected a hash with :item and :priority keys' unless item_with_priority.is_a?(Hash) push(item_with_priority[:item], priority: item_with_priority[:priority]) end |
#change_priority(item, new_priority) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/philiprehberger/priority_queue.rb', line 64 def change_priority(item, new_priority) idx = @item_index[item] raise ArgumentError, "Item not found in queue: #{item.inspect}" if idx.nil? old_priority = @heap[idx][0] @heap[idx] = [new_priority, @heap[idx][1], item] cmp = @comparator.call(new_priority, old_priority) if cmp.negative? bubble_up(idx) elsif cmp.positive? bubble_down(idx) end self end |
#clear ⇒ Object
88 89 90 91 92 93 |
# File 'lib/philiprehberger/priority_queue.rb', line 88 def clear @heap.clear @item_index.clear @size = 0 self end |
#delete(item) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/philiprehberger/priority_queue.rb', line 120 def delete(item) idx = @item_index[item] return nil if idx.nil? if idx == @size - 1 entry = @heap.pop @size -= 1 @item_index.delete(item) return entry[2] end swap(idx, @size - 1) entry = @heap.pop @size -= 1 @item_index.delete(item) bubble_up(idx) bubble_down(idx) entry[2] end |
#drain ⇒ Object
114 115 116 117 118 |
# File 'lib/philiprehberger/priority_queue.rb', line 114 def drain result = [] result << pop until empty? result end |
#each(&block) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/philiprehberger/priority_queue.rb', line 95 def each(&block) return enum_for(:each) unless block sorted = @heap.sort { |a, b| compare_entries(a, b) } sorted.each { |entry| block.call(entry[2], entry[0]) } self end |
#empty? ⇒ Boolean
60 61 62 |
# File 'lib/philiprehberger/priority_queue.rb', line 60 def empty? @size.zero? end |
#include?(item) ⇒ Boolean
84 85 86 |
# File 'lib/philiprehberger/priority_queue.rb', line 84 def include?(item) @item_index.key?(item) end |
#merge(other) ⇒ Object
144 145 146 147 148 149 |
# File 'lib/philiprehberger/priority_queue.rb', line 144 def merge(other) merged = self.class.new(&@comparator) @heap.each { |entry| merged.push(entry[2], priority: entry[0]) } other.each_entry { |entry| merged.push(entry[2], priority: entry[0]) } merged end |
#peek ⇒ Object
54 55 56 57 58 |
# File 'lib/philiprehberger/priority_queue.rb', line 54 def peek return nil if empty? @heap[0][2] end |
#peek_priority ⇒ Object
108 109 110 111 112 |
# File 'lib/philiprehberger/priority_queue.rb', line 108 def peek_priority return nil if empty? @heap[0][0] end |
#pop ⇒ Object
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/philiprehberger/priority_queue.rb', line 43 def pop return nil if empty? swap(0, @size - 1) entry = @heap.pop @size -= 1 @item_index.delete(entry[2]) bubble_down(0) unless empty? entry[2] end |
#priorities ⇒ Object
140 141 142 |
# File 'lib/philiprehberger/priority_queue.rb', line 140 def priorities @heap.map { |entry| entry[0] }.uniq.sort end |
#push(item, priority:) ⇒ Object
27 28 29 30 31 32 33 34 35 |
# File 'lib/philiprehberger/priority_queue.rb', line 27 def push(item, priority:) entry = [priority, @insertion_counter, item] @insertion_counter += 1 @heap << entry @item_index[item] = @size @size += 1 bubble_up(@size - 1) self end |
#push_many(items) ⇒ Object
103 104 105 106 |
# File 'lib/philiprehberger/priority_queue.rb', line 103 def push_many(items) items.each { |h| push(h[:item], priority: h[:priority]) } self end |
#to_a ⇒ Object
80 81 82 |
# File 'lib/philiprehberger/priority_queue.rb', line 80 def to_a @heap.sort { |a, b| compare_entries(a, b) }.map { |entry| entry[2] } end |