victory 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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