victory 0.0.0 → 0.0.1

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +11 -1
  4. data/README.md +4 -6
  5. data/Rakefile +11 -4
  6. data/USAGE.md +159 -0
  7. data/ext/algorithms/string/LICENSE.md +21 -0
  8. data/ext/algorithms/string/extconf.rb +4 -0
  9. data/ext/algorithms/string/string.c +68 -0
  10. data/ext/containers/bst/LICENSE.md +21 -0
  11. data/ext/containers/bst/bst.c +247 -0
  12. data/ext/containers/bst/extconf.rb +4 -0
  13. data/ext/containers/deque/LICENSE.md +21 -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/LICENSE.md +21 -0
  17. data/ext/containers/rbtree_map/extconf.rb +4 -0
  18. data/ext/containers/rbtree_map/rbtree.c +498 -0
  19. data/ext/containers/splaytree_map/LICENSE.md +21 -0
  20. data/ext/containers/splaytree_map/extconf.rb +4 -0
  21. data/ext/containers/splaytree_map/splaytree.c +419 -0
  22. data/ext/containers/xor_list/extconf.rb +4 -0
  23. data/ext/containers/xor_list/xor_list.c +122 -0
  24. data/lib/algorithms/search.rb +104 -0
  25. data/lib/algorithms/sort.rb +389 -0
  26. data/lib/algorithms/string.rb +29 -0
  27. data/lib/containers/deque.rb +193 -0
  28. data/lib/containers/heap.rb +524 -0
  29. data/lib/containers/kd_tree.rb +131 -0
  30. data/lib/containers/list.rb +81 -0
  31. data/lib/containers/prefix_tree.rb +61 -0
  32. data/lib/containers/priority_queue.rb +135 -0
  33. data/lib/containers/queue.rb +89 -0
  34. data/lib/containers/rb_tree_map.rb +420 -0
  35. data/lib/containers/splay_tree_map.rb +290 -0
  36. data/lib/containers/stack.rb +88 -0
  37. data/lib/containers/suffix_array.rb +92 -0
  38. data/lib/containers/trie.rb +204 -0
  39. data/lib/containers/tuple.rb +20 -0
  40. data/lib/victory/version.rb +1 -1
  41. data/lib/victory.rb +8 -1
  42. data/victory.gemspec +12 -3
  43. metadata +73 -12
  44. data/.idea/encodings.xml +0 -4
  45. data/.idea/misc.xml +0 -7
  46. data/.idea/modules.xml +0 -8
  47. data/.idea/victory.iml +0 -13
  48. data/.idea/workspace.xml +0 -233
  49. data/ext/victory/extconf.rb +0 -3
  50. data/ext/victory/victory.c +0 -9
  51. data/ext/victory/victory.h +0 -6
@@ -0,0 +1,420 @@
1
+ require 'containers/stack'
2
+ # rdoc
3
+ # A RBTreeMap is a map that is stored in sorted order based on the order of its keys. This ordering is
4
+ # determined by applying the function <=> to compare the keys. No duplicate values for keys are allowed,
5
+ # so duplicate values are overwritten.
6
+ #
7
+ # A major advantage of RBTreeMap over a Hash is the fact that keys are stored in order and can thus be
8
+ # iterated over in order. This is useful for many datasets.
9
+ #
10
+ # The implementation is adapted from Robert Sedgewick's Left Leaning Red-Black Tree implementation,
11
+ # which can be found at http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
12
+ #
13
+ # Containers::RBTreeMap automatically uses the faster C implementation if it was built
14
+ # when the gem was installed. Alternatively, Containers::RubyRBTreeMap and Containers::CRBTreeMap can be
15
+ # explicitly used as well; their functionality is identical.
16
+ #
17
+ # Most methods have O(log n) complexity.
18
+ #
19
+ #
20
+ # MIT License
21
+ #
22
+ # Copyright (c) 2009 Kanwei Li
23
+ #
24
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
25
+ # of this software and associated documentation files (the "Software"), to deal
26
+ # in the Software without restriction, including without limitation the rights
27
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28
+ # copies of the Software, and to permit persons to whom the Software is
29
+ # furnished to do so, subject to the following conditions:
30
+ #
31
+ # The above copyright notice and this permission notice shall be included in all
32
+ # copies or substantial portions of the Software.
33
+ #
34
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40
+ # SOFTWARE.
41
+ #
42
+ class Containers::RubyRBTreeMap
43
+ include Enumerable
44
+
45
+ attr_accessor :height_black
46
+
47
+ # Create and initialize a new empty TreeMap.
48
+ def initialize
49
+ @root = nil
50
+ @height_black = 0
51
+ end
52
+
53
+ # Insert an item with an associated key into the TreeMap, and returns the item inserted
54
+ #
55
+ # Complexity: O(log n)
56
+ #
57
+ # map = Containers::TreeMap.new
58
+ # map.push("MA", "Massachusetts") #=> "Massachusetts"
59
+ # map.get("MA") #=> "Massachusetts"
60
+ def push(key, value)
61
+ @root = insert(@root, key, value)
62
+ @height_black += 1 if isred(@root)
63
+ @root.color = :black
64
+ value
65
+ end
66
+ alias_method :[]=, :push
67
+
68
+ # Return the number of items in the TreeMap.
69
+ #
70
+ # map = Containers::TreeMap.new
71
+ # map.push("MA", "Massachusetts")
72
+ # map.push("GA", "Georgia")
73
+ # map.size #=> 2
74
+ def size
75
+ @root and @root.size or 0
76
+ end
77
+
78
+ # Return the height of the tree structure in the TreeMap.
79
+ #
80
+ # Complexity: O(1)
81
+ #
82
+ # map = Containers::TreeMap.new
83
+ # map.push("MA", "Massachusetts")
84
+ # map.push("GA", "Georgia")
85
+ # map.height #=> 2
86
+ def height
87
+ @root and @root.height or 0
88
+ end
89
+
90
+ # Return true if key is found in the TreeMap, false otherwise
91
+ #
92
+ # Complexity: O(log n)
93
+ #
94
+ # map = Containers::TreeMap.new
95
+ # map.push("MA", "Massachusetts")
96
+ # map.push("GA", "Georgia")
97
+ # map.has_key?("GA") #=> true
98
+ # map.has_key?("DE") #=> false
99
+ def has_key?(key)
100
+ !get(key).nil?
101
+ end
102
+
103
+ # Return the item associated with the key, or nil if none found.
104
+ #
105
+ # Complexity: O(log n)
106
+ #
107
+ # map = Containers::TreeMap.new
108
+ # map.push("MA", "Massachusetts")
109
+ # map.push("GA", "Georgia")
110
+ # map.get("GA") #=> "Georgia"
111
+ def get(key)
112
+ get_recursive(@root, key)
113
+ end
114
+ alias_method :[], :get
115
+
116
+ # Return the smallest key in the map.
117
+ #
118
+ # Complexity: O(log n)
119
+ #
120
+ # map = Containers::TreeMap.new
121
+ # map.push("MA", "Massachusetts")
122
+ # map.push("GA", "Georgia")
123
+ # map.min_key #=> "GA"
124
+ def min_key
125
+ @root.nil? ? nil : min_recursive(@root)
126
+ end
127
+
128
+ # Return the largest key in the map.
129
+ #
130
+ # Complexity: O(log n)
131
+ #
132
+ # map = Containers::TreeMap.new
133
+ # map.push("MA", "Massachusetts")
134
+ # map.push("GA", "Georgia")
135
+ # map.max_key #=> "MA"
136
+ def max_key
137
+ @root.nil? ? nil : max_recursive(@root)
138
+ end
139
+
140
+ # Deletes the item and key if it's found, and returns the item. Returns nil
141
+ # if key is not present.
142
+ #
143
+ # !!! Warning !!! There is a currently a bug in the delete method that occurs rarely
144
+ # but often enough, especially in large datasets. It is currently under investigation.
145
+ #
146
+ # Complexity: O(log n)
147
+ #
148
+ # map = Containers::TreeMap.new
149
+ # map.push("MA", "Massachusetts")
150
+ # map.push("GA", "Georgia")
151
+ # map.min_key #=> "GA"
152
+ def delete(key)
153
+ result = nil
154
+ if @root
155
+ @root, result = delete_recursive(@root, key)
156
+ @root.color = :black if @root
157
+ end
158
+ result
159
+ end
160
+
161
+ # Returns true if the tree is empty, false otherwise
162
+ def empty?
163
+ @root.nil?
164
+ end
165
+
166
+ # Deletes the item with the smallest key and returns the item. Returns nil
167
+ # if key is not present.
168
+ #
169
+ # Complexity: O(log n)
170
+ #
171
+ # map = Containers::TreeMap.new
172
+ # map.push("MA", "Massachusetts")
173
+ # map.push("GA", "Georgia")
174
+ # map.delete_min #=> "Massachusetts"
175
+ # map.size #=> 1
176
+ def delete_min
177
+ result = nil
178
+ if @root
179
+ @root, result = delete_min_recursive(@root)
180
+ @root.color = :black if @root
181
+ end
182
+ result
183
+ end
184
+
185
+ # Deletes the item with the smallest key and returns the item. Returns nil
186
+ # if key is not present.
187
+ #
188
+ # Complexity: O(log n)
189
+ #
190
+ # map = Containers::TreeMap.new
191
+ # map.push("MA", "Massachusetts")
192
+ # map.push("GA", "Georgia")
193
+ # map.delete_max #=> "Georgia"
194
+ # map.size #=> 1
195
+ def delete_max
196
+ result = nil
197
+ if @root
198
+ @root, result = delete_max_recursive(@root)
199
+ @root.color = :black if @root
200
+ end
201
+ result
202
+ end
203
+
204
+ # Iterates over the TreeMap from smallest to largest element. Iterative approach.
205
+ def each
206
+ return nil unless @root
207
+ stack = Containers::Stack.new
208
+ cursor = @root
209
+ loop do
210
+ if cursor
211
+ stack.push(cursor)
212
+ cursor = cursor.left
213
+ else
214
+ unless stack.empty?
215
+ cursor = stack.pop
216
+ yield(cursor.key, cursor.value)
217
+ cursor = cursor.right
218
+ else
219
+ break
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ class Node # :nodoc: all
226
+ attr_accessor :color, :key, :value, :left, :right, :size, :height
227
+ def initialize(key, value)
228
+ @key = key
229
+ @value = value
230
+ @color = :red
231
+ @left = nil
232
+ @right = nil
233
+ @size = 1
234
+ @height = 1
235
+ end
236
+
237
+ def red?
238
+ @color == :red
239
+ end
240
+
241
+ def colorflip
242
+ @color = @color == :red ? :black : :red
243
+ @left.color = @left.color == :red ? :black : :red
244
+ @right.color = @right.color == :red ? :black : :red
245
+ end
246
+
247
+ def update_size
248
+ @size = (@left ? @left.size : 0) + (@right ? @right.size : 0) + 1
249
+ left_height = (@left ? @left.height : 0)
250
+ right_height = (@right ? @right.height : 0)
251
+ if left_height > right_height
252
+ @height = left_height + 1
253
+ else
254
+ @height = right_height + 1
255
+ end
256
+ self
257
+ end
258
+
259
+ def rotate_left
260
+ r = @right
261
+ r_key, r_value, r_color = r.key, r.value, r.color
262
+ b = r.left
263
+ r.left = @left
264
+ @left = r
265
+ @right = r.right
266
+ r.right = b
267
+ r.color, r.key, r.value = :red, @key, @value
268
+ @key, @value = r_key, r_value
269
+ r.update_size
270
+ update_size
271
+ end
272
+
273
+ def rotate_right
274
+ l = @left
275
+ l_key, l_value, l_color = l.key, l.value, l.color
276
+ b = l.right
277
+ l.right = @right
278
+ @right = l
279
+ @left = l.left
280
+ l.left = b
281
+ l.color, l.key, l.value = :red, @key, @value
282
+ @key, @value = l_key, l_value
283
+ l.update_size
284
+ update_size
285
+ end
286
+
287
+ def move_red_left
288
+ colorflip
289
+ if (@right.left && @right.left.red?)
290
+ @right.rotate_right
291
+ rotate_left
292
+ colorflip
293
+ end
294
+ self
295
+ end
296
+
297
+ def move_red_right
298
+ colorflip
299
+ if (@left.left && @left.left.red?)
300
+ rotate_right
301
+ colorflip
302
+ end
303
+ self
304
+ end
305
+
306
+ def fixup
307
+ rotate_left if @right && @right.red?
308
+ rotate_right if (@left && @left.red?) && (@left.left && @left.left.red?)
309
+ colorflip if (@left && @left.red?) && (@right && @right.red?)
310
+
311
+ update_size
312
+ end
313
+ end
314
+
315
+ def delete_recursive(node, key)
316
+ if (key <=> node.key) == -1
317
+ node.move_red_left if ( !isred(node.left) && !isred(node.left.left) )
318
+ node.left, result = delete_recursive(node.left, key)
319
+ else
320
+ node.rotate_right if isred(node.left)
321
+ if ( ( (key <=> node.key) == 0) && node.right.nil? )
322
+ return nil, node.value
323
+ end
324
+ if ( !isred(node.right) && !isred(node.right.left) )
325
+ node.move_red_right
326
+ end
327
+ if (key <=> node.key) == 0
328
+ result = node.value
329
+ node.value = get_recursive(node.right, min_recursive(node.right))
330
+ node.key = min_recursive(node.right)
331
+ node.right = delete_min_recursive(node.right).first
332
+ else
333
+ node.right, result = delete_recursive(node.right, key)
334
+ end
335
+ end
336
+ return node.fixup, result
337
+ end
338
+ private :delete_recursive
339
+
340
+ def delete_min_recursive(node)
341
+ if node.left.nil?
342
+ return nil, node.value
343
+ end
344
+ if ( !isred(node.left) && !isred(node.left.left) )
345
+ node.move_red_left
346
+ end
347
+ node.left, result = delete_min_recursive(node.left)
348
+
349
+ return node.fixup, result
350
+ end
351
+ private :delete_min_recursive
352
+
353
+ def delete_max_recursive(node)
354
+ if (isred(node.left))
355
+ node = node.rotate_right
356
+ end
357
+ return nil, node.value if node.right.nil?
358
+ if ( !isred(node.right) && !isred(node.right.left) )
359
+ node.move_red_right
360
+ end
361
+ node.right, result = delete_max_recursive(node.right)
362
+
363
+ return node.fixup, result
364
+ end
365
+ private :delete_max_recursive
366
+
367
+ def get_recursive(node, key)
368
+ return nil if node.nil?
369
+ case key <=> node.key
370
+ when 0 then return node.value
371
+ when -1 then return get_recursive(node.left, key)
372
+ when 1 then return get_recursive(node.right, key)
373
+ end
374
+ end
375
+ private :get_recursive
376
+
377
+ def min_recursive(node)
378
+ return node.key if node.left.nil?
379
+
380
+ min_recursive(node.left)
381
+ end
382
+ private :min_recursive
383
+
384
+ def max_recursive(node)
385
+ return node.key if node.right.nil?
386
+
387
+ max_recursive(node.right)
388
+ end
389
+ private :max_recursive
390
+
391
+ def insert(node, key, value)
392
+ return Node.new(key, value) unless node
393
+
394
+ case key <=> node.key
395
+ when 0 then node.value = value
396
+ when -1 then node.left = insert(node.left, key, value)
397
+ when 1 then node.right = insert(node.right, key, value)
398
+ end
399
+
400
+ node.rotate_left if (node.right && node.right.red?)
401
+ node.rotate_right if (node.left && node.left.red? && node.left.left && node.left.left.red?)
402
+ node.colorflip if (node.left && node.left.red? && node.right && node.right.red?)
403
+ node.update_size
404
+ end
405
+ private :insert
406
+
407
+ def isred(node)
408
+ return false if node.nil?
409
+
410
+ node.color == :red
411
+ end
412
+ private :isred
413
+ end
414
+
415
+ begin
416
+ require 'CRBTreeMap'
417
+ Containers::RBTreeMap = Containers::CRBTreeMap
418
+ rescue LoadError # C Version could not be found, try ruby version
419
+ Containers::RBTreeMap = Containers::RubyRBTreeMap
420
+ end
@@ -0,0 +1,290 @@
1
+ require 'containers/stack'
2
+ # rdoc
3
+ # A SplayTreeMap is a map that is stored in ascending order of its keys, determined by applying
4
+ # the function <=> to compare keys. No duplicate values for keys are allowed, so new values of a key
5
+ # overwrites the old value of the key.
6
+ #
7
+ # A major advantage of SplayTreeMap over a Hash is the fact that keys are stored in order and can thus be
8
+ # iterated over in order. Also, Splay Trees are self-optimizing as recently accessed nodes stay near
9
+ # the root and are easily re-accessed later. Splay Trees are also more simply implemented than Red-Black
10
+ # trees.
11
+ #
12
+ # Splay trees have amortized O(log n) performance for most methods, but are O(n) worst case. This happens
13
+ # when keys are added in sorted order, causing the tree to have a height of the number of items added.
14
+ #
15
+ #
16
+ # MIT License
17
+ #
18
+ # Copyright (c) 2009 Kanwei Li
19
+ #
20
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ # of this software and associated documentation files (the "Software"), to deal
22
+ # in the Software without restriction, including without limitation the rights
23
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ # copies of the Software, and to permit persons to whom the Software is
25
+ # furnished to do so, subject to the following conditions:
26
+ #
27
+ # The above copyright notice and this permission notice shall be included in all
28
+ # copies or substantial portions of the Software.
29
+ #
30
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
+ # SOFTWARE.
37
+ class Containers::RubySplayTreeMap
38
+ include Enumerable
39
+
40
+ Node = Struct.new(:key, :value, :left, :right)
41
+
42
+ # Create and initialize a new empty SplayTreeMap.
43
+ def initialize
44
+ @size = 0
45
+ clear
46
+ end
47
+
48
+ # Insert an item with an associated key into the SplayTreeMap, and returns the item inserted
49
+ #
50
+ # Complexity: amortized O(log n)
51
+ #
52
+ # map = Containers::SplayTreeMap.new
53
+ # map.push("MA", "Massachusetts") #=> "Massachusetts"
54
+ # map.get("MA") #=> "Massachusetts"
55
+ def push(key, value)
56
+ if @root.nil?
57
+ @root = Node.new(key, value, nil, nil)
58
+ @size = 1
59
+ return value
60
+ end
61
+ splay(key)
62
+
63
+ cmp = (key <=> @root.key)
64
+ if cmp == 0
65
+ @root.value = value
66
+ return value
67
+ end
68
+ node = Node.new(key, value, nil, nil)
69
+ if cmp < 1
70
+ node.left = @root.left
71
+ node.right = @root
72
+ @root.left = nil
73
+ else
74
+ node.right = @root.right
75
+ node.left = @root
76
+ @root.right = nil
77
+ end
78
+ @root = node
79
+ @size += 1
80
+ value
81
+ end
82
+ alias_method :[]=, :push
83
+
84
+ # Return the number of items in the SplayTreeMap.
85
+ #
86
+ # map = Containers::SplayTreeMap.new
87
+ # map.push("MA", "Massachusetts")
88
+ # map.push("GA", "Georgia")
89
+ # map.size #=> 2
90
+ def size
91
+ @size
92
+ end
93
+
94
+ # Remove all elements from the SplayTreeMap
95
+ #
96
+ # Complexity: O(1)
97
+ #
98
+ def clear
99
+ @root = nil
100
+ @size = 0
101
+ @header = Node.new(nil, nil, nil, nil)
102
+ end
103
+
104
+ # Return the height of the tree structure in the SplayTreeMap.
105
+ #
106
+ # Complexity: O(log n)
107
+ #
108
+ # map = Containers::SplayTreeMap.new
109
+ # map.push("MA", "Massachusetts")
110
+ # map.push("GA", "Georgia")
111
+ # map.height #=> 2
112
+ def height
113
+ height_recursive(@root)
114
+ end
115
+
116
+ # Return true if key is found in the SplayTreeMap, false otherwise.
117
+ #
118
+ # Complexity: amortized O(log n)
119
+ #
120
+ # map = Containers::SplayTreeMap.new
121
+ # map["MA"] = "Massachusetts"
122
+ # map["GA"] = "Georgia"
123
+ # map.has_key?("GA") #=> true
124
+ # map.has_key?("DE") #=> false
125
+ def has_key?(key)
126
+ !get(key).nil?
127
+ end
128
+
129
+ # Return the item associated with the key, or nil if none found.
130
+ #
131
+ # Complexity: amortized O(log n)
132
+ #
133
+ # map = Containers::SplayTreeMap.new
134
+ # map.push("MA", "Massachusetts")
135
+ # map.push("GA", "Georgia")
136
+ # map.get("GA") #=> "Georgia"
137
+ def get(key)
138
+ return nil if @root.nil?
139
+
140
+ splay(key)
141
+ (@root.key <=> key) == 0 ? @root.value : nil
142
+ end
143
+ alias_method :[], :get
144
+
145
+ # Return the smallest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
146
+ #
147
+ # Complexity: amortized O(log n)
148
+ #
149
+ # map = Containers::SplayTreeMap.new
150
+ # map["MA"] = "Massachusetts"
151
+ # map["GA"] = "Georgia"
152
+ # map.min #=> ["GA", "Georgia"]
153
+ def min
154
+ return nil if @root.nil?
155
+ n = @root
156
+ while n.left
157
+ n = n.left
158
+ end
159
+ splay(n.key)
160
+ return [n.key, n.value]
161
+ end
162
+
163
+ # Return the largest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
164
+ #
165
+ # Complexity: amortized O(log n)
166
+ #
167
+ # map = Containers::SplayTreeMap.new
168
+ # map["MA"] = "Massachusetts"
169
+ # map["GA"] = "Georgia"
170
+ # map.max #=> ["MA", "Massachusetts"]
171
+ def max
172
+ return nil if @root.nil?
173
+ n = @root
174
+ while n.right
175
+ n = n.right
176
+ end
177
+ splay(n.key)
178
+ return [n.key, n.value]
179
+ end
180
+
181
+ # Deletes the item and key if it's found, and returns the item. Returns nil
182
+ # if key is not present.
183
+ #
184
+ # Complexity: amortized O(log n)
185
+ #
186
+ # map = Containers::SplayTreeMap.new
187
+ # map["MA"] = "Massachusetts"
188
+ # map["GA"] = "Georgia"
189
+ # map.delete("GA") #=> "Georgia"
190
+ # map.delete("DE") #=> nil
191
+ def delete(key)
192
+ return nil if @root.nil?
193
+ deleted = nil
194
+ splay(key)
195
+ if (key <=> @root.key) == 0 # The key exists
196
+ deleted = @root.value
197
+ if @root.left.nil?
198
+ @root = @root.right
199
+ else
200
+ x = @root.right
201
+ @root = @root.left
202
+ splay(key)
203
+ @root.right = x
204
+ end
205
+ end
206
+ deleted
207
+ end
208
+
209
+ # Iterates over the SplayTreeMap in ascending order. Uses an iterative, not recursive, approach.
210
+ def each
211
+ return nil unless @root
212
+ stack = Containers::Stack.new
213
+ cursor = @root
214
+ loop do
215
+ if cursor
216
+ stack.push(cursor)
217
+ cursor = cursor.left
218
+ else
219
+ unless stack.empty?
220
+ cursor = stack.pop
221
+ yield(cursor.key, cursor.value)
222
+ cursor = cursor.right
223
+ else
224
+ break
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ # Moves a key to the root, updating the structure in each step.
231
+ def splay(key)
232
+ l, r = @header, @header
233
+ t = @root
234
+ @header.left, @header.right = nil, nil
235
+
236
+ loop do
237
+ if (key <=> t.key) == -1
238
+ break unless t.left
239
+ if (key <=> t.left.key) == -1
240
+ y = t.left
241
+ t.left = y.right
242
+ y.right = t
243
+ t = y
244
+ break unless t.left
245
+ end
246
+ r.left = t
247
+ r = t
248
+ t = t.left
249
+ elsif (key <=> t.key) == 1
250
+ break unless t.right
251
+ if (key <=> t.right.key) == 1
252
+ y = t.right
253
+ t.right = y.left
254
+ y.left = t
255
+ t = y
256
+ break unless t.right
257
+ end
258
+ l.right = t
259
+ l = t
260
+ t = t.right
261
+ else
262
+ break
263
+ end
264
+ end
265
+ l.right = t.left
266
+ r.left = t.right
267
+ t.left = @header.right
268
+ t.right = @header.left
269
+ @root = t
270
+ end
271
+ private :splay
272
+
273
+ # Recursively determine height
274
+ def height_recursive(node)
275
+ return 0 if node.nil?
276
+
277
+ left_height = 1 + height_recursive(node.left)
278
+ right_height = 1 + height_recursive(node.right)
279
+
280
+ left_height > right_height ? left_height : right_height
281
+ end
282
+ private :height_recursive
283
+ end
284
+
285
+ begin
286
+ require 'CSplayTreeMap'
287
+ Containers::SplayTreeMap = Containers::CSplayTreeMap
288
+ rescue LoadError # C Version could not be found, try ruby version
289
+ Containers::SplayTreeMap = Containers::RubySplayTreeMap
290
+ end