algorithms 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/History.txt +139 -2
  2. data/Manifest +31 -8
  3. data/README +90 -0
  4. data/Rakefile +22 -9
  5. data/algorithms.gemspec +28 -101
  6. data/benchmark.rb +29 -27
  7. data/benchmarks/rbench.rb +16 -0
  8. data/benchmarks/rbench/column.rb +26 -0
  9. data/benchmarks/rbench/group.rb +43 -0
  10. data/benchmarks/rbench/report.rb +53 -0
  11. data/benchmarks/rbench/runner.rb +109 -0
  12. data/benchmarks/rbench/summary.rb +51 -0
  13. data/benchmarks/sorts.rb +33 -0
  14. data/ext/containers/bst/bst.c +205 -0
  15. data/ext/containers/{priority_queue → bst}/extconf.rb +1 -1
  16. data/ext/containers/deque/deque.c +233 -0
  17. data/ext/containers/deque/extconf.rb +4 -0
  18. data/ext/containers/tree_map/extconf.rb +1 -1
  19. data/ext/containers/tree_map/rbtree.c +73 -25
  20. data/lib/algorithms.rb +65 -6
  21. data/lib/algorithms/search.rb +84 -0
  22. data/lib/algorithms/sort.rb +238 -0
  23. data/lib/containers/deque.rb +176 -0
  24. data/lib/containers/heap.rb +451 -111
  25. data/lib/containers/kd_tree.rb +87 -0
  26. data/lib/containers/priority_queue.rb +107 -508
  27. data/lib/containers/queue.rb +62 -23
  28. data/lib/containers/rb_tree_map.rb +398 -0
  29. data/lib/containers/splay_tree_map.rb +274 -0
  30. data/lib/containers/stack.rb +59 -21
  31. data/lib/containers/suffix_array.rb +68 -0
  32. data/lib/containers/trie.rb +182 -0
  33. data/lib/graphs/graph.rb +25 -0
  34. data/spec/bst_spec.rb +31 -0
  35. data/spec/deque_spec.rb +108 -0
  36. data/spec/heap_spec.rb +111 -66
  37. data/spec/kd_tree_spec.rb +89 -0
  38. data/spec/priority_queue_spec.rb +71 -27
  39. data/spec/queue_spec.rb +53 -45
  40. data/spec/rb_tree_map_spec.rb +123 -0
  41. data/spec/search_spec.rb +28 -0
  42. data/spec/sort_spec.rb +28 -0
  43. data/spec/splay_tree_map_spec.rb +102 -0
  44. data/spec/stack_spec.rb +56 -49
  45. data/spec/suffix_array_spec.rb +40 -0
  46. data/spec/trie_spec.rb +59 -0
  47. metadata +54 -32
  48. data/README.txt +0 -58
  49. data/ext/containers/priority_queue/priority_queue.c +0 -948
  50. data/ext/containers/tree_map/Rakefile +0 -4
  51. data/lib/containers/hash.rb +0 -0
  52. data/lib/containers/tree_map.rb +0 -265
  53. data/spec/priority_queue_test.rb +0 -371
  54. data/spec/tree_map_spec.rb +0 -99
@@ -0,0 +1,87 @@
1
+ =begin rdoc
2
+
3
+ A kd-tree allows searching of points in multi-dimensional space, increasing
4
+ efficiency for nearest-neighbor searching in particular.
5
+
6
+ =end
7
+
8
+ class Containers::KDTree
9
+ Node = Struct.new(:id, :coords, :left, :right)
10
+
11
+ def initialize(points)
12
+ @root = build_tree(points)
13
+ @nearest = []
14
+ end
15
+
16
+ # Build a kd-tree
17
+ def build_tree(points, depth=0)
18
+ return if points.empty?
19
+
20
+ axis = depth % 2
21
+
22
+ points.sort! { |a, b| a[1][axis] <=> b[1][axis] }
23
+ median = points.size / 2
24
+
25
+ node = Node.new(points[median][0], points[median][1], nil, nil)
26
+ node.left = build_tree(points[0...median], depth+1)
27
+ node.right = build_tree(points[median+1..-1], depth+1)
28
+ node
29
+ end
30
+ private :build_tree
31
+
32
+ # Euclidian distanced, squared, between a node and target coords
33
+ def distance2(node, target)
34
+ return nil if node.nil? or target.nil?
35
+ c = (node.coords[0] - target[0])
36
+ d = (node.coords[1] - target[1])
37
+ c * c + d * d
38
+ end
39
+ private :distance2
40
+
41
+ # Update array of nearest elements if necessary
42
+ def check_nearest(nearest, node, target, k_nearest)
43
+ d = distance2(node, target)
44
+ if nearest.size < k_nearest || d < nearest.last[0]
45
+ nearest.pop if nearest.size >= k_nearest
46
+ nearest << [d, node.id]
47
+ nearest.sort! { |a, b| a[0] <=> b[0] }
48
+ end
49
+ nearest
50
+ end
51
+
52
+ # Find k closest points to given coordinates
53
+ def find_nearest(target, k_nearest)
54
+ @nearest = []
55
+ nearest(@root, target, k_nearest, 0)
56
+ end
57
+
58
+ def nearest(node, target, k_nearest, depth)
59
+ axis = depth % 2
60
+
61
+ if node.left.nil? && node.right.nil? # Leaf node
62
+ @nearest = check_nearest(@nearest, node, target, k_nearest)
63
+ return
64
+ end
65
+
66
+ # Go down the nearest split
67
+ if node.right.nil? || (node.left && target[axis] <= node.coords[axis])
68
+ nearer = node.left
69
+ further = node.right
70
+ else
71
+ nearer = node.right
72
+ further = node.left
73
+ end
74
+ nearest(nearer, target, k_nearest, depth+1)
75
+
76
+ # See if we have to check other side
77
+ if further
78
+ if @nearest.size < k_nearest || (target[axis] - node.coords[axis])**2 < @nearest.last[0]
79
+ nearest(further, target, k_nearest, depth+1)
80
+ end
81
+ end
82
+
83
+ @nearest = check_nearest(@nearest, node, target, k_nearest)
84
+ end
85
+ private :nearest
86
+
87
+ end
@@ -1,514 +1,113 @@
1
- # This is a fibonacci heap priority queue implementation.
2
- # (c) 2005 Brian Amberg
3
- # Please submit bugreports to mail@brian-amberg.de
1
+ require 'containers/heap'
4
2
 
5
- # Modifications by Kanwei Li
6
- module Containers
7
- class RubyPriorityQueue
8
- include Enumerable
3
+ =begin rdoc
4
+ A Priority Queue is a data structure that behaves like a queue except that elements have an
5
+ associated priority. The #next and #pop methods return the item with the next highest priority.
9
6
 
10
- # Returns the number of elements of the queue.
11
- #
12
- # q = PriorityQueue.new
13
- # q.length #=> 0
14
- # q[0] = 1
15
- # q.length #=> 1
16
- attr_reader :length
17
-
18
- # Create a new, empty PriorityQueue
19
- def initialize
20
- @nodes = Hash.new
21
- @rootlist = nil
22
- @min = nil
23
- @length = 0
24
- end
25
-
26
- # Print a priority queue as a dot-graph. The output can be fed to dot from the
27
- # vizgraph suite to create a tree depicting the internal datastructure.
28
- def to_dot
29
- r = ["digraph fibheap {"]
30
- #r << @rootlist.to_dot.join("\n") if @rootlist
31
- r << "ROOT -> #{@rootlist.dot_id};" if @rootlist
32
- @nodes.to_a.sort.each do | (_, n) |
33
- r << " #{n.dot_id} [label=\"#{n.key}: #{n.priority}\"];"
34
- r << " #{n.dot_id} -> #{n.right.dot_id} [constraint=false];" if n.right# and n.dot_id < n.right.dot_id
35
- r << " #{n.dot_id} -> #{n.left.dot_id} [constraint=false];" if n.left #and n.dot_id < n.left.dot_id
36
- r << " #{n.dot_id} -> #{n.child.dot_id}" if n.child
37
- end
38
- r << "}"
39
- r.join("\n")
40
- r
41
- end
42
-
43
- # Call dot and gv displaying the datstructure
44
- def display_dot
45
- puts to_dot
46
- system "echo '#{to_dot}' | twopi -Tps -Groot=ROOT -Goverlap=false> /tmp/dotfile.ps; gv /tmp/dotfile.ps"
47
- end
48
-
49
- # call-seq:
50
- # [key] = priority
51
- # change_priority(key, priority)
52
- # push(key, priority)
53
- #
54
- # Set the priority of a key.
55
- #
56
- # q = PriorityQueue.new
57
- # q["car"] = 50
58
- # q["train"] = 50
59
- # q["bike"] = 10
60
- # q.min #=> ["bike", 10]
61
- # q["car"] = 0
62
- # q.min #=> ["car", 0]
63
- def change_priority(key, priority)
64
- return push(key, priority) unless @nodes[key]
65
-
66
- n = @nodes[key]
67
- if n.priority < priority # Priority was increased. Remove the node and reinsert.
68
- self.delete(key)
69
- self.push(key, priority);
70
- return self
71
- end
72
- n.priority = priority;
73
- @min = n if n.priority < @min.priority
74
-
75
- return self if !n.parent or n.parent.priority <= n.priority # Already in rootlist or bigger than parent
76
- begin # Cascading Cuts
77
- p = n.parent
78
- cut_node(n)
79
- n = p
80
- end while n.mark and n.parent
81
- n.mark = true if n.parent
82
-
83
- self
84
- end
85
-
86
- # Add an object to the queue.
87
- def push(key, priority)
88
- return change_priority(key, priority) if @nodes[key]
89
- @nodes[key] = node = Node.new(key, priority)
90
- @min = node if !@min or priority < @min.priority
91
- if not @rootlist
92
- @rootlist = node
93
- node.left = node.right = node
94
- else
95
- node.left = @rootlist.left
96
- node.right = @rootlist
97
- @rootlist.left.right = node
98
- @rootlist.left = node
99
- end
100
- @length += 1
101
- self
102
- end
103
-
104
- # Returns true if the array is empty, false otherwise.
105
- def empty?
106
- @rootlist.nil?
107
- end
108
-
109
- # call-seq:
110
- # [key] -> priority
111
- #
112
- # Return the priority of a key or nil if the key is not in the queue.
113
- #
114
- # q = PriorityQueue.new
115
- # (0..10).each do | i | q[i.to_s] = i end
116
- # q["5"] #=> 5
117
- # q[5] #=> nil
118
- def [](key)
119
- @nodes[key] and @nodes[key].priority
120
- end
121
-
122
- # call-seq:
123
- # has_key? key -> boolean
124
- #
125
- # Return false if the key is not in the queue, true otherwise.
126
- #
127
- # q = PriorityQueue.new
128
- # (0..10).each do | i | q[i.to_s] = i end
129
- # q.has_key("5") #=> true
130
- # q.has_key(5) #=> false
131
- def has_key?(key)
132
- @nodes.has_key?(key)
133
- end
134
-
135
- alias :[]= :push
136
-
137
- # Call the given block with each [key, priority] pair in the queue
138
- #
139
- # Beware: Changing the queue in the block may lead to unwanted behaviour and
140
- # even infinite loops.
141
- def each
142
- @nodes.each do | key, node |
143
- yield(key, node.priority)
144
- end
145
- end
146
-
147
- # call-seq:
148
- # min -> [object, priority]
149
- #
150
- # Return the pair [object, priority] with minimal priority or nil when the
151
- # queue is empty.
152
- #
153
- # q = PriorityQueue.new
154
- # q["a"] = 10
155
- # q["b"] = 20
156
- # q.min #=> ["a", 10]
157
- # q.delete_min #=> ["a", 10]
158
- # q.min #=> ["b", 20]
159
- # q.delete_min #=> ["b", 20]
160
- # q.min #=> nil
161
- def min
162
- [@min.key, @min.priority] rescue nil
163
- end
164
-
165
- # call-seq:
166
- # min_key -> object
167
- #
168
- # Return the key that has the minimal priority or nil when the queue is empty.
169
- #
170
- # q = PriorityQueue.new
171
- # q["a"] = 10
172
- # q["b"] = 20
173
- # q.min_key #=> "a"
174
- # q.delete_min #=> ["a", 10]
175
- # q.min_key #=> "b"
176
- # q.delete_min #=> ["b", 20]
177
- # q.min_key #=> nil
178
- def min_key
179
- @min.key rescue nil
180
- end
181
-
182
- # call-seq:
183
- # min_priority -> priority
184
- #
185
- # Return the minimal priority or nil when the queue is empty.
186
- #
187
- # q = PriorityQueue.new
188
- # q["a"] = 10
189
- # q["b"] = 20
190
- # q.min_priority #=> 10
191
- # q.delete_min #=> ["a", 10]
192
- # q.min_priority #=> 20
193
- # q.delete_min #=> ["b", 20]
194
- # q.min_priority #=> nil
195
- def min_priority
196
- @min.priority rescue nil
197
- end
198
-
199
- # call-seq:
200
- # delete(key) -> [key, priority]
201
- # delete(key) -> nil
202
- #
203
- # Delete a key from the priority queue. Returns nil when the key was not in
204
- # the queue and [key, priority] otherwise.
205
- #
206
- # q = PriorityQueue.new
207
- # (0..10).each do | i | q[i.to_s] = i end
208
- # q.delete(5) #=> ["5", 5]
209
- # q.delete(5) #=> nil
210
- def delete(key)
211
- return nil unless n = @nodes.delete(key)
212
-
213
- if n.child
214
- c = n.child
215
- e = n.child
216
- begin
217
- r = c.right
218
- cut_node(c)
219
- c = r
220
- end while c != e
221
- end
222
- cut_node(n) if n.parent
223
-
224
- if n == n.right
225
- @min = nil;
226
- @rootlist = nil;
227
- else
228
- @rootlist = n.right if @rootlist == n
229
- if @min == n
230
- n1 = n.right
231
- @min = n1
232
- begin
233
- @min = n1 if n1.priority < @min.priority
234
- n1 = n1.right
235
- end while(n1 != n);
236
- end
237
- n.right.left = n.left
238
- n.left.right = n.right
239
- n.left = n
240
- n.right = n
241
- end
242
- @length -= 1
243
- return [n.key, n.priority]
244
- end
245
-
246
- # call-seq:
247
- # delete_min_return_key -> key
248
- #
249
- # Delete key with minimal priority and return the key
250
- #
251
- # q = PriorityQueue.new
252
- # q["a"] = 1
253
- # q["b"] = 0
254
- # q.delete_min_return_key #=> "b"
255
- # q.delete_min_return_key #=> "a"
256
- # q.delete_min_return_key #=> nil
257
- def delete_min_return_key
258
- delete_min[0] rescue nil
259
- end
260
-
261
- # call-seq:
262
- # delete_min_return_priority -> priority
263
- #
264
- # Delete key with minimal priority and return the priority value
265
- #
266
- # q = PriorityQueue.new
267
- # q["a"] = 1
268
- # q["b"] = 0
269
- # q.delete_min_return_priority #=> 0
270
- # q.delete_min_return_priority #=> 1
271
- # q.delete_min_return_priority #=> nil
272
- def delete_min_return_priority
273
- delete_min[1] rescue nil
274
- end
275
-
276
- # call-seq:
277
- # delete_min -> [key, priority]
278
- #
279
- # Delete key with minimal priority and return [key, priority]
280
- #
281
- # q = PriorityQueue.new
282
- # q["a"] = 1
283
- # q["b"] = 0
284
- # q.delete_min #=> ["b", 0]
285
- # q.delete_min #=> ["a", 1]
286
- # q.delete_min #=> nil
287
- def delete_min
288
- return nil if self.empty?
289
- result = self.min
290
-
291
- @nodes.delete(@min.key)
292
-
293
- if @length == 1
294
- @rootlist = @min = nil
295
- @length = 0
296
- else
297
- min = @min
298
- if @min == @rootlist # If the rootlist is anchored at the minimum, shift to the right
299
- if @rootlist == @rootlist.right
300
- @rootlist = @min = nil
301
- else
302
- @rootlist = @min = @min.right
303
- end
304
- end
305
- min.left.right = min.right;
306
- min.right.left = min.left;
307
- min.left = min.right = min;
308
- if min.child
309
- # Kinder und Eltern trennen, Markierung aufheben
310
- n = min.child;
311
- begin
312
- n.parent = nil;
313
- n.mark = false;
314
- n = n.right;
315
- end while n != min.child
316
-
317
- # Kinder einf�gen
318
- if @rootlist
319
- l1 = @rootlist.left
320
- l2 = n.left
321
-
322
- l1.right = n
323
- n.left = l1
324
- l2.right = @rootlist
325
- @rootlist.left = l2
326
- else
327
- @rootlist = n
328
- end
329
- end
330
-
331
- # Gr��e anpassen
332
- @length -= 1
333
-
334
- # Wieder aufh�bschen
335
- consolidate
336
- end
337
-
338
- result
339
- end
340
-
341
- # Returns a string representation of the priority queue.
342
- def inspect
343
- "<PriorityQueue: #{@nodes.map{|(_, n)| [n.key, n.priority]}.sort_by{|(_,p)|p}.inspect}>"
344
- end
345
-
346
- def initialize_copy(copy)
347
- copy_nodes = @nodes
348
- @nodes = {}
349
-
350
- copy_nodes.each do | (_, cn) |
351
- n = @nodes[cn.key] = Node.new(cn.key, cn.priority)
352
- n.mark = cn.mark
353
- n.degree = cn.degree
354
- end
355
-
356
- copy_nodes.each do | (_, cn) |
357
- n = @nodes[cn.key]
358
- n.left = @nodes[cn.left.key] if cn.left
359
- n.right = @nodes[cn.right.key] if cn.right
360
- n.parent = @nodes[cn.parent.key] if cn.parent
361
- n.child = @nodes[cn.child.key] if cn.child
362
- end
363
- @rootlist = @nodes[@rootlist.key] if @rootlist
364
- @min = @nodes[@min.key] if @min
365
- self
366
- end
367
-
368
- # Node class used internally
369
- class Node # :nodoc:
370
- attr_accessor :parent, :child, :left, :right, :key, :priority, :degree, :mark
371
-
372
- def child=(c)
373
- raise "Circular Child" if c == self
374
- raise "Child is neighbour" if c == self.right
375
- raise "Child is neighbour" if c == self.left
376
- @child = c
377
- end
378
-
379
- def to_dot(only_down = false, known_nodes = [])
380
- p known_nodes.map { | n | n.dot_id }
381
- p self.dot_id
382
- result = []
383
- if only_down
384
- raise "Circular #{caller.inspect}" if known_nodes.include?(self)
385
- known_nodes << self
386
-
387
- result << "#{dot_id} [label=\"#{@key}: #{@priority}\"];"
388
- l = " "
389
- #l << "#{@left.dot_id} <- #{dot_id}; " if @left
390
- l << "#{dot_id} -> #{@left.dot_id} [constraint=false]; " if @left and @left.dot_id < self.dot_id
391
- l << "#{dot_id} -> #{@right.dot_id} [constraint=false];\t\t\t\t/*neighbours*/" if @right and @right.dot_id <= self.dot_id
392
- result << l
393
- result << " #{dot_id} -> #{@child.dot_id}; //child" if @child
394
- result << @child.to_dot(false, known_nodes) if @child
395
- else
396
- n = self
397
- begin
398
- result.concat(n.to_dot(true, known_nodes))
399
- n = n.right
400
- end while n != self
401
- end
402
- result.flatten.map{|r| " " << r}
403
- end
404
-
405
- def dot_id
406
- "N#{@key}"
407
- end
408
-
409
- def initialize(key, priority)
410
- @key = key; @priority = priority; @degree = 0
411
- end
412
- end
7
+ Priority Queues are often used in graph problems, such as Dijkstra's Algorithm for shortest
8
+ path, and the A* search algorithm for shortest path.
413
9
 
414
-
415
- private
416
-
417
- def link_nodes(b1, b2)
418
- return link_nodes(b2, b1) if b2.priority < b1.priority
419
-
420
- b2.parent = b1
421
- child = b1.child
422
- b1.child = b2
423
- if child
424
- b2.left = child.left
425
- b2.left.right = b2
426
- b2.right = child
427
- child.left = b2
428
- else
429
- b2.left = b2
430
- b2.right = b2
431
- end
432
- b1.degree += 1
433
- b2.mark = false # TODO: Check if this is correct, or if b1 should be marked as false
434
- return b1
435
- end
436
-
437
- # Does not change length
438
- def delete_first
439
- return nil unless @rootlist
440
-
441
- result = @rootlist
442
- if result == result.right
443
- @min = @rootlist = nil
444
- else
445
- @rootlist = result.right
446
- @rootlist.left = result.left
447
- @rootlist.left.right = @rootlist
448
-
449
- result.right = result.left = result
450
- end
451
- return result;
452
- end
453
-
454
- def cut_node(n)
455
- return self unless n.parent
456
- n.parent.degree -= 1
457
- if n.parent.child == n
458
- if n.right == n
459
- n.parent.child = nil
460
- else
461
- n.parent.child = n.right;
462
- end
463
- end
464
- n.parent = nil
465
- n.right.left = n.left
466
- n.left.right = n.right
467
-
468
- n.right = @rootlist
469
- n.left = @rootlist.left
470
- @rootlist.left.right = n
471
- @rootlist.left = n
472
-
473
- n.mark = false
474
-
475
- return self
476
- end
477
-
478
- # Does not change length
479
- def insert_tree(tree)
480
- if @rootlist == nil
481
- @rootlist = @min = tree
482
- else
483
- l = @rootlist.left
484
- l.right = tree
485
- @rootlist.left = tree
486
- tree.left = l
487
- tree.right = @rootlist
488
- @min = tree if tree.priority < @min.priority
489
- end
490
- self
491
- end
492
-
493
- def consolidate
494
- return self if self.empty?
495
- array_size = (2.0 * Math.log(self.length) / Math.log(2) + 1.0).ceil
496
- tree_by_degree = Array.new(array_size)
497
-
498
- while n = delete_first
499
- while n1 = tree_by_degree[n.degree]
500
- tree_by_degree[n.degree] = nil;
501
- n = link_nodes(n, n1);
502
- end
503
- tree_by_degree[n.degree] = n;
504
- end
10
+ This container is implemented using the Fibonacci heap included in the Collections library.
11
+ =end
12
+ class Containers::PriorityQueue
13
+ include Enumerable
14
+
15
+ # Create a new, empty PriorityQueue
16
+ def initialize(&block)
17
+ # We default to a priority queue that returns the largest value
18
+ block ||= lambda { |x, y| (x <=> y) == 1 }
19
+ @heap = Containers::Heap.new(&block)
20
+ end
21
+
22
+ # Returns the number of elements in the queue.
23
+ #
24
+ # q = Containers::PriorityQueue.new
25
+ # q.size #=> 0
26
+ # q.push("Alaska", 1)
27
+ # q.size #=> 1
28
+ def size
29
+ @heap.size
30
+ end
31
+ alias_method :length, :size
32
+
33
+ # Add an object to the queue with associated priority.
34
+ #
35
+ # q = Containers::PriorityQueue.new
36
+ # q.push("Alaska", 1)
37
+ # q.pop #=> "Alaska"
38
+ def push(object, priority)
39
+ @heap.push(priority, object)
40
+ end
41
+
42
+ # Clears all the items in the queue.
43
+ def clear
44
+ @heap.clear
45
+ end
46
+
47
+ # Returns true if the queue is empty, false otherwise.
48
+ def empty?
49
+ @heap.empty?
50
+ end
505
51
 
506
- @rootlist = @min = nil;
507
- tree_by_degree.each do | tree |
508
- next unless tree
509
- insert_tree(tree)
510
- end
511
- self
512
- end
52
+ # call-seq:
53
+ # has_priority? priority -> boolean
54
+ #
55
+ # Return true if the priority is in the queue, false otherwise.
56
+ #
57
+ # q = PriorityQueue.new
58
+ # q.push("Alaska", 1)
59
+ #
60
+ # q.has_priority?(1) #=> true
61
+ # q.has_priority?(2) #=> false
62
+ def has_priority?(priority)
63
+ @heap.has_key?(priority)
64
+ end
65
+
66
+ # call-seq:
67
+ # next -> object
68
+ #
69
+ # Return the object with the next highest priority, but does not remove it
70
+ #
71
+ # q = Containers::PriorityQueue.new
72
+ # q.push("Alaska", 50)
73
+ # q.push("Delaware", 30)
74
+ # q.push("Georgia", 35)
75
+ # q.next #=> "Alaska"
76
+ def next
77
+ @heap.next
513
78
  end
79
+
80
+ # call-seq:
81
+ # pop -> object
82
+ #
83
+ # Return the object with the next highest priority and removes it from the queue
84
+ #
85
+ # q = Containers::PriorityQueue.new
86
+ # q.push("Alaska", 50)
87
+ # q.push("Delaware", 30)
88
+ # q.push("Georgia", 35)
89
+ # q.pop #=> "Alaska"
90
+ # q.size #=> 2
91
+ def pop
92
+ @heap.pop
93
+ end
94
+ alias_method :next!, :pop
95
+
96
+ # call-seq:
97
+ # delete(priority) -> object
98
+ # delete(priority) -> nil
99
+ #
100
+ # Delete an object with specified priority from the queue. If there are duplicates, an
101
+ # arbitrary object with that priority is deleted and returned. Returns nil if there are
102
+ # no objects with the priority.
103
+ #
104
+ # q = PriorityQueue.new
105
+ # q.push("Alaska", 50)
106
+ # q.push("Delaware", 30)
107
+ # q.delete(50) #=> "Alaska"
108
+ # q.delete(10) #=> nil
109
+ def delete(priority)
110
+ @heap.delete(priority)
111
+ end
112
+
514
113
  end