algorithms 0.6.1-java

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 (53) hide show
  1. data/CHANGELOG.markdown +193 -0
  2. data/Gemfile +9 -0
  3. data/Manifest +51 -0
  4. data/README.markdown +84 -0
  5. data/Rakefile +18 -0
  6. data/algorithms.gemspec +23 -0
  7. data/benchmarks/deque.rb +17 -0
  8. data/benchmarks/sorts.rb +34 -0
  9. data/benchmarks/treemaps.rb +51 -0
  10. data/ext/algorithms/string/extconf.rb +4 -0
  11. data/ext/algorithms/string/string.c +68 -0
  12. data/ext/containers/bst/bst.c +247 -0
  13. data/ext/containers/bst/extconf.rb +4 -0
  14. data/ext/containers/deque/deque.c +247 -0
  15. data/ext/containers/deque/extconf.rb +4 -0
  16. data/ext/containers/rbtree_map/extconf.rb +4 -0
  17. data/ext/containers/rbtree_map/rbtree.c +498 -0
  18. data/ext/containers/splaytree_map/extconf.rb +4 -0
  19. data/ext/containers/splaytree_map/splaytree.c +419 -0
  20. data/lib/algorithms.rb +65 -0
  21. data/lib/algorithms/search.rb +84 -0
  22. data/lib/algorithms/sort.rb +238 -0
  23. data/lib/algorithms/string.rb +9 -0
  24. data/lib/containers/deque.rb +171 -0
  25. data/lib/containers/heap.rb +502 -0
  26. data/lib/containers/kd_tree.rb +110 -0
  27. data/lib/containers/priority_queue.rb +113 -0
  28. data/lib/containers/queue.rb +68 -0
  29. data/lib/containers/rb_tree_map.rb +398 -0
  30. data/lib/containers/splay_tree_map.rb +269 -0
  31. data/lib/containers/stack.rb +67 -0
  32. data/lib/containers/suffix_array.rb +68 -0
  33. data/lib/containers/trie.rb +182 -0
  34. data/spec/bst_gc_mark_spec.rb +25 -0
  35. data/spec/bst_spec.rb +25 -0
  36. data/spec/deque_gc_mark_spec.rb +18 -0
  37. data/spec/deque_spec.rb +108 -0
  38. data/spec/heap_spec.rb +131 -0
  39. data/spec/kd_expected_out.txt +10000 -0
  40. data/spec/kd_test_in.txt +10000 -0
  41. data/spec/kd_tree_spec.rb +34 -0
  42. data/spec/map_gc_mark_spec.rb +29 -0
  43. data/spec/priority_queue_spec.rb +75 -0
  44. data/spec/queue_spec.rb +61 -0
  45. data/spec/rb_tree_map_spec.rb +123 -0
  46. data/spec/search_spec.rb +28 -0
  47. data/spec/sort_spec.rb +28 -0
  48. data/spec/splay_tree_map_spec.rb +106 -0
  49. data/spec/stack_spec.rb +60 -0
  50. data/spec/string_spec.rb +15 -0
  51. data/spec/suffix_array_spec.rb +40 -0
  52. data/spec/trie_spec.rb +59 -0
  53. metadata +106 -0
@@ -0,0 +1,502 @@
1
+ =begin rdoc
2
+ A Heap is a container that satisfies the heap property that nodes are always smaller in
3
+ value than their parent node.
4
+
5
+ The Containers::Heap class is flexible and upon initialization, takes an optional block
6
+ that determines how the items are ordered. Two versions that are included are the
7
+ Containers::MaxHeap and Containers::MinHeap that return the largest and smallest items on
8
+ each invocation, respectively.
9
+
10
+ This library implements a Fibonacci heap, which allows O(1) complexity for most methods.
11
+ =end
12
+ class Containers::Heap
13
+ include Enumerable
14
+
15
+ # call-seq:
16
+ # size -> int
17
+ #
18
+ # Return the number of elements in the heap.
19
+ def size
20
+ @size
21
+ end
22
+ alias_method :length, :size
23
+
24
+ # call-seq:
25
+ # Heap.new(optional_array) { |x, y| optional_comparison_fn } -> new_heap
26
+ #
27
+ # If an optional array is passed, the entries in the array are inserted into the heap with
28
+ # equal key and value fields. Also, an optional block can be passed to define the function
29
+ # that maintains heap property. For example, a min-heap can be created with:
30
+ #
31
+ # minheap = Heap.new { |x, y| (x <=> y) == -1 }
32
+ # minheap.push(6)
33
+ # minheap.push(10)
34
+ # minheap.pop #=> 6
35
+ #
36
+ # Thus, smaller elements will be parent nodes. The heap defaults to a min-heap if no block
37
+ # is given.
38
+ def initialize(ary=[], &block)
39
+ @compare_fn = block || lambda { |x, y| (x <=> y) == -1 }
40
+ @next = nil
41
+ @size = 0
42
+ @stored = {}
43
+
44
+ ary.each { |n| push(n) } unless ary.empty?
45
+ end
46
+
47
+ # call-seq:
48
+ # push(key, value) -> value
49
+ # push(value) -> value
50
+ #
51
+ # Inserts an item with a given key into the heap. If only one parameter is given,
52
+ # the key is set to the value.
53
+ #
54
+ # Complexity: O(1)
55
+ #
56
+ # heap = MinHeap.new
57
+ # heap.push(1, "Cat")
58
+ # heap.push(2)
59
+ # heap.pop #=> "Cat"
60
+ # heap.pop #=> 2
61
+ def push(key, value=key)
62
+ raise ArgumentError, "Heap keys must not be nil." unless key
63
+ node = Node.new(key, value)
64
+ # Add new node to the left of the @next node
65
+ if @next
66
+ node.right = @next
67
+ node.left = @next.left
68
+ node.left.right = node
69
+ @next.left = node
70
+ if @compare_fn[key, @next.key]
71
+ @next = node
72
+ end
73
+ else
74
+ @next = node
75
+ end
76
+ @size += 1
77
+
78
+ arr = []
79
+ w = @next.right
80
+ until w == @next do
81
+ arr << w.value
82
+ w = w.right
83
+ end
84
+ arr << @next.value
85
+ @stored[key] ||= []
86
+ @stored[key] << node
87
+ value
88
+ end
89
+ alias_method :<<, :push
90
+
91
+ # call-seq:
92
+ # has_key?(key) -> true or false
93
+ #
94
+ # Returns true if heap contains the key.
95
+ #
96
+ # Complexity: O(1)
97
+ #
98
+ # minheap = MinHeap.new([1, 2])
99
+ # minheap.has_key?(2) #=> true
100
+ # minheap.has_key?(4) #=> false
101
+ def has_key?(key)
102
+ @stored[key] && !@stored[key].empty? ? true : false
103
+ end
104
+
105
+ # call-seq:
106
+ # next -> value
107
+ # next -> nil
108
+ #
109
+ # Returns the value of the next item in heap order, but does not remove it.
110
+ #
111
+ # Complexity: O(1)
112
+ #
113
+ # minheap = MinHeap.new([1, 2])
114
+ # minheap.next #=> 1
115
+ # minheap.size #=> 2
116
+ def next
117
+ @next && @next.value
118
+ end
119
+
120
+ # call-seq:
121
+ # next_key -> key
122
+ # next_key -> nil
123
+ #
124
+ # Returns the key associated with the next item in heap order, but does not remove the value.
125
+ #
126
+ # Complexity: O(1)
127
+ #
128
+ # minheap = MinHeap.new
129
+ # minheap.push(1, :a)
130
+ # minheap.next_key #=> 1
131
+ #
132
+ def next_key
133
+ @next && @next.key
134
+ end
135
+
136
+ # call-seq:
137
+ # clear -> nil
138
+ #
139
+ # Removes all elements from the heap, destructively.
140
+ #
141
+ # Complexity: O(1)
142
+ #
143
+ def clear
144
+ @next = nil
145
+ @size = 0
146
+ @stored = {}
147
+ nil
148
+ end
149
+
150
+ # call-seq:
151
+ # empty? -> true or false
152
+ #
153
+ # Returns true if the heap is empty, false otherwise.
154
+ def empty?
155
+ @next.nil?
156
+ end
157
+
158
+ # call-seq:
159
+ # merge!(otherheap) -> merged_heap
160
+ #
161
+ # Does a shallow merge of all the nodes in the other heap.
162
+ #
163
+ # Complexity: O(1)
164
+ #
165
+ # heap = MinHeap.new([5, 6, 7, 8])
166
+ # otherheap = MinHeap.new([1, 2, 3, 4])
167
+ # heap.merge!(otherheap)
168
+ # heap.size #=> 8
169
+ # heap.pop #=> 1
170
+ def merge!(otherheap)
171
+ raise ArgumentError, "Trying to merge a heap with something not a heap" unless otherheap.kind_of? Containers::Heap
172
+ other_root = otherheap.instance_variable_get("@next")
173
+ if other_root
174
+ @stored = @stored.merge(otherheap.instance_variable_get("@stored")) { |key, a, b| (a << b).flatten }
175
+ # Insert othernode's @next node to the left of current @next
176
+ @next.left.right = other_root
177
+ ol = other_root.left
178
+ other_root.left = @next.left
179
+ ol.right = @next
180
+ @next.left = ol
181
+
182
+ @next = other_root if @compare_fn[other_root.key, @next.key]
183
+ end
184
+ @size += otherheap.size
185
+ end
186
+
187
+ # call-seq:
188
+ # pop -> value
189
+ # pop -> nil
190
+ #
191
+ # Returns the value of the next item in heap order and removes it from the heap.
192
+ #
193
+ # Complexity: O(1)
194
+ #
195
+ # minheap = MinHeap.new([1, 2])
196
+ # minheap.pop #=> 1
197
+ # minheap.size #=> 1
198
+ def pop
199
+ return nil unless @next
200
+ popped = @next
201
+ if @size == 1
202
+ clear
203
+ return popped.value
204
+ end
205
+ # Merge the popped's children into root node
206
+ if @next.child
207
+ @next.child.parent = nil
208
+
209
+ # get rid of parent
210
+ sibling = @next.child.right
211
+ until sibling == @next.child
212
+ sibling.parent = nil
213
+ sibling = sibling.right
214
+ end
215
+
216
+ # Merge the children into the root. If @next is the only root node, make its child the @next node
217
+ if @next.right == @next
218
+ @next = @next.child
219
+ else
220
+ next_left, next_right = @next.left, @next.right
221
+ current_child = @next.child
222
+ @next.right.left = current_child
223
+ @next.left.right = current_child.right
224
+ current_child.right.left = next_left
225
+ current_child.right = next_right
226
+ @next = @next.right
227
+ end
228
+ else
229
+ @next.left.right = @next.right
230
+ @next.right.left = @next.left
231
+ @next = @next.right
232
+ end
233
+ consolidate
234
+
235
+ unless @stored[popped.key].delete(popped)
236
+ raise "Couldn't delete node from stored nodes hash"
237
+ end
238
+ @size -= 1
239
+
240
+ popped.value
241
+ end
242
+ alias_method :next!, :pop
243
+
244
+ # call-seq:
245
+ # change_key(key, new_key) -> [new_key, value]
246
+ # change_key(key, new_key) -> nil
247
+ #
248
+ # Changes the key from one to another. Doing so must not violate the heap property or
249
+ # an exception will be raised. If the key is found, an array containing the new key and
250
+ # value pair is returned, otherwise nil is returned.
251
+ #
252
+ # In the case of duplicate keys, an arbitrary key is changed. This will be investigated
253
+ # more in the future.
254
+ #
255
+ # Complexity: amortized O(1)
256
+ #
257
+ # minheap = MinHeap.new([1, 2])
258
+ # minheap.change_key(2, 3) #=> raise error since we can't increase the value in a min-heap
259
+ # minheap.change_key(2, 0) #=> [0, 2]
260
+ # minheap.pop #=> 2
261
+ # minheap.pop #=> 1
262
+ def change_key(key, new_key, delete=false)
263
+ return if @stored[key].nil? || @stored[key].empty? || (key == new_key)
264
+
265
+ # Must maintain heap property
266
+ raise "Changing this key would not maintain heap property!" unless (delete || @compare_fn[new_key, key])
267
+ node = @stored[key].shift
268
+ if node
269
+ node.key = new_key
270
+ @stored[new_key] ||= []
271
+ @stored[new_key] << node
272
+ parent = node.parent
273
+ if parent
274
+ # if heap property is violated
275
+ if delete || @compare_fn[new_key, parent.key]
276
+ cut(node, parent)
277
+ cascading_cut(parent)
278
+ end
279
+ end
280
+ if delete || @compare_fn[node.key, @next.key]
281
+ @next = node
282
+ end
283
+ return [node.key, node.value]
284
+ end
285
+ nil
286
+ end
287
+
288
+ # call-seq:
289
+ # delete(key) -> value
290
+ # delete(key) -> nil
291
+ #
292
+ # Deletes the item with associated key and returns it. nil is returned if the key
293
+ # is not found. In the case of nodes with duplicate keys, an arbitrary one is deleted.
294
+ #
295
+ # Complexity: amortized O(log n)
296
+ #
297
+ # minheap = MinHeap.new([1, 2])
298
+ # minheap.delete(1) #=> 1
299
+ # minheap.size #=> 1
300
+ def delete(key)
301
+ pop if change_key(key, nil, true)
302
+ end
303
+
304
+ # Node class used internally
305
+ class Node # :nodoc:
306
+ attr_accessor :parent, :child, :left, :right, :key, :value, :degree, :marked
307
+
308
+ def initialize(key, value)
309
+ @key = key
310
+ @value = value
311
+ @degree = 0
312
+ @marked = false
313
+ @right = self
314
+ @left = self
315
+ end
316
+
317
+ def marked?
318
+ @marked == true
319
+ end
320
+
321
+ end
322
+
323
+ # make node a child of a parent node
324
+ def link_nodes(child, parent)
325
+ # link the child's siblings
326
+ child.left.right = child.right
327
+ child.right.left = child.left
328
+
329
+ child.parent = parent
330
+
331
+ # if parent doesn't have children, make new child its only child
332
+ if parent.child.nil?
333
+ parent.child = child.right = child.left = child
334
+ else # otherwise insert new child into parent's children list
335
+ current_child = parent.child
336
+ child.left = current_child
337
+ child.right = current_child.right
338
+ current_child.right.left = child
339
+ current_child.right = child
340
+ end
341
+ parent.degree += 1
342
+ child.marked = false
343
+ end
344
+ private :link_nodes
345
+
346
+ # Makes sure the structure does not contain nodes in the root list with equal degrees
347
+ def consolidate
348
+ roots = []
349
+ root = @next
350
+ min = root
351
+ # find the nodes in the list
352
+ loop do
353
+ roots << root
354
+ root = root.right
355
+ break if root == @next
356
+ end
357
+ degrees = []
358
+ roots.each do |root|
359
+ min = root if @compare_fn[root.key, min.key]
360
+ # check if we need to merge
361
+ if degrees[root.degree].nil? # no other node with the same degree
362
+ degrees[root.degree] = root
363
+ next
364
+ else # there is another node with the same degree, consolidate them
365
+ degree = root.degree
366
+ until degrees[degree].nil? do
367
+ other_root_with_degree = degrees[degree]
368
+ if @compare_fn[root.key, other_root_with_degree.key] # determine which node is the parent, which one is the child
369
+ smaller, larger = root, other_root_with_degree
370
+ else
371
+ smaller, larger = other_root_with_degree, root
372
+ end
373
+ link_nodes(larger, smaller)
374
+ degrees[degree] = nil
375
+ root = smaller
376
+ degree += 1
377
+ end
378
+ degrees[degree] = root
379
+ min = root if min.key == root.key # this fixes a bug with duplicate keys not being in the right order
380
+ end
381
+ end
382
+ @next = min
383
+ end
384
+ private :consolidate
385
+
386
+ def cascading_cut(node)
387
+ p = node.parent
388
+ if p
389
+ if node.marked?
390
+ cut(node, p)
391
+ cascading_cut(p)
392
+ else
393
+ node.marked = true
394
+ end
395
+ end
396
+ end
397
+ private :cascading_cut
398
+
399
+ # remove x from y's children and add x to the root list
400
+ def cut(x, y)
401
+ x.left.right = x.right
402
+ x.right.left = x.left
403
+ y.degree -= 1
404
+ if (y.degree == 0)
405
+ y.child = nil
406
+ elsif (y.child == x)
407
+ y.child = x.right
408
+ end
409
+ x.right = @next
410
+ x.left = @next.left
411
+ @next.left = x
412
+ x.left.right = x
413
+ x.parent = nil
414
+ x.marked = false
415
+ end
416
+ private :cut
417
+
418
+ end
419
+
420
+ # A MaxHeap is a heap where the items are returned in descending order of key value.
421
+ class Containers::MaxHeap < Containers::Heap
422
+
423
+ # call-seq:
424
+ # MaxHeap.new(ary) -> new_heap
425
+ #
426
+ # Creates a new MaxHeap with an optional array parameter of items to insert into the heap.
427
+ # A MaxHeap is created by calling Heap.new { |x, y| (x <=> y) == 1 }, so this is a convenience class.
428
+ #
429
+ # maxheap = MaxHeap.new([1, 2, 3, 4])
430
+ # maxheap.pop #=> 4
431
+ # maxheap.pop #=> 3
432
+ def initialize(ary=[])
433
+ super(ary) { |x, y| (x <=> y) == 1 }
434
+ end
435
+
436
+ # call-seq:
437
+ # max -> value
438
+ # max -> nil
439
+ #
440
+ # Returns the item with the largest key, but does not remove it from the heap.
441
+ #
442
+ # maxheap = MaxHeap.new([1, 2, 3, 4])
443
+ # maxheap.max #=> 4
444
+ def max
445
+ self.next
446
+ end
447
+
448
+ # call-seq:
449
+ # max! -> value
450
+ # max! -> nil
451
+ #
452
+ # Returns the item with the largest key and removes it from the heap.
453
+ #
454
+ # maxheap = MaxHeap.new([1, 2, 3, 4])
455
+ # maxheap.max! #=> 4
456
+ # maxheap.size #=> 3
457
+ def max!
458
+ self.pop
459
+ end
460
+ end
461
+
462
+ # A MinHeap is a heap where the items are returned in ascending order of key value.
463
+ class Containers::MinHeap < Containers::Heap
464
+
465
+ # call-seq:
466
+ # MinHeap.new(ary) -> new_heap
467
+ #
468
+ # Creates a new MinHeap with an optional array parameter of items to insert into the heap.
469
+ # A MinHeap is created by calling Heap.new { |x, y| (x <=> y) == -1 }, so this is a convenience class.
470
+ #
471
+ # minheap = MinHeap.new([1, 2, 3, 4])
472
+ # minheap.pop #=> 1
473
+ # minheap.pop #=> 2
474
+ def initialize(ary=[])
475
+ super(ary) { |x, y| (x <=> y) == -1 }
476
+ end
477
+
478
+ # call-seq:
479
+ # min -> value
480
+ # min -> nil
481
+ #
482
+ # Returns the item with the smallest key, but does not remove it from the heap.
483
+ #
484
+ # minheap = MinHeap.new([1, 2, 3, 4])
485
+ # minheap.min #=> 1
486
+ def min
487
+ self.next
488
+ end
489
+
490
+ # call-seq:
491
+ # min! -> value
492
+ # min! -> nil
493
+ #
494
+ # Returns the item with the smallest key and removes it from the heap.
495
+ #
496
+ # minheap = MinHeap.new([1, 2, 3, 4])
497
+ # minheap.min! #=> 1
498
+ # minheap.size #=> 3
499
+ def min!
500
+ self.pop
501
+ end
502
+ end