DSA 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9927035d95a766e70b9f202d3ccba141d2665bd
4
+ data.tar.gz: 78444502a579279fe7d288e4fe48a5f24684a7f7
5
+ SHA512:
6
+ metadata.gz: cf06eb363bfdc2b9e7aee1b746a73f106ac7919df4dc229008b32e9c06d06265ce1157a6191ad0c0af775b04a56c19e7007c78dd89d7b10b9450f89e9ae3191e
7
+ data.tar.gz: 34e8770d943e932144dcd1e9d61034f1fee333655ee128c32b033110ac9c3c5be3f890fd8da9fa778d7f5edb8aa04dbe08941cd856778963f6e4cc794706bc57
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.idea
19
+
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'DSA/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "DSA"
8
+ spec.version = DSA::VERSION
9
+ spec.authors = ["lusaisai"]
10
+ spec.email = ["lusaisai@163.com"]
11
+ spec.summary = %q{Data Structures and Algorithms in Ruby}
12
+ spec.description = %q{List, BinarySearchTree(RedBlackTree), PriorityQueue, (Array/List)Stack and Queue}
13
+ spec.homepage = "https://github.com/lusaisai/DSA"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ end
24
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in DSA.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2014 lusaisai
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
@@ -0,0 +1,127 @@
1
+ # DSA
2
+
3
+ Ruby gem for basic Data Structures and Algorithms
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'DSA'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install DSA
18
+
19
+ ## Usage
20
+
21
+ To include the package,
22
+
23
+ require 'DSA'
24
+
25
+
26
+ ### List
27
+ A doubly linked list data structure. Use when there are lots of insertions/deletions in the middle,
28
+ otherwise, built-in array is better.
29
+
30
+ l = DSA::List.new
31
+ l.push 'some value'
32
+ l.pop
33
+ l.unshift 'some value'
34
+ l.shift
35
+ l.first
36
+ l.last
37
+ l.empty?
38
+ l.length
39
+
40
+ General access/removal/insertion using index is supported, these operations require linear time, so use carefully.
41
+
42
+ l[2]
43
+ l.insert_at 10, 'some value'
44
+ l.remove_at 2
45
+
46
+ To do lots of insertions/deletions, use the iterator, StopIteration is raised when reaching to head or tail
47
+
48
+ li = l.begin_iterator # the iterator starts from the head
49
+ puts li.next
50
+ li.insert 'some value'
51
+ li.remove
52
+ li.update 'new value'
53
+
54
+ li = l.end_iterator # the iterator starts from the tail
55
+ li.previous
56
+
57
+ Enumerable is included, all those method such as 'each' are all available, since other methods are based on each,
58
+ the performance might not be the best, use only when a full traversal is inevitable.
59
+
60
+ ### BinarySearchTree
61
+ An ordered map, works like a hash, but preserves an order and provides range search, implemented as a RedBlack tree.
62
+
63
+ The following three are aliases in creating a new object,
64
+
65
+ rb = DSA::BinarySearchTree.new
66
+ rb = DSA::OrderedMap.new
67
+ rb = DSA::RedBlackTree.new
68
+
69
+ Method are very like a hash,
70
+
71
+ rb[key] = value
72
+ rb[key]
73
+ rb.delete key
74
+
75
+ And special methods related to orders, those methods yield key/value pairs to block, if no block, enumerator is returned.
76
+
77
+ rb.each # in-order traversal
78
+ rb.gt(key) # key/value pairs for keys greater than key
79
+ rb.ge(key)
80
+ rb.lt(key)
81
+ rb.le(key)
82
+
83
+ A help method tried to print a tree, not quite pretty, but may helps test
84
+
85
+ rb.bfs_print
86
+
87
+ Enumerable is included, all those method such as 'each' are all available, since other methods are based on each,
88
+ the performance might not be the best, use only when a full traversal is inevitable.
89
+
90
+
91
+ ### PriorityQueue
92
+ An array based heap, priority is a number, the smaller it is, higher priority it has
93
+
94
+ pq = DSA::PriorityQueue.new
95
+ pq.add 10, 'some job'
96
+ pq.length
97
+ pq.top # look at the highest priority without removing it
98
+ job = pq.pop # get and remove the highest priority job
99
+
100
+
101
+ ### Stack and Queue
102
+ Implemented based on array or list.
103
+
104
+ s = DSA::ArrayStack.new
105
+ s = DSA::ListStack.new
106
+ s.push 'some value'
107
+ s.pop
108
+ s.empty?
109
+ s.top
110
+ s.length
111
+
112
+ q = DSA::ArrayQueue.new
113
+ q = DSA::ListQueue.new
114
+ q.enqueue 'some value'
115
+ q.dequeue
116
+ q.empty?
117
+ q.first
118
+ q.length
119
+
120
+ ### Algorithm
121
+ The following functions are for demonstrations, specially sort, using built-in Array#bsearch and Array#sort instead,
122
+ they have a better performance.
123
+
124
+ DSA::Algorithm::factorial(5)
125
+ DSA::Algorithm::binary_search((1..9).to_a, 2, 0, 8)
126
+ DSA::Algorithm::insertion_sort!(array)
127
+ DSA::Algorithm::quick_sort!(array, 0, array.length-1)
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,10 @@
1
+ require_relative 'DSA/version'
2
+ require_relative 'DSA/algorithm'
3
+ require_relative 'DSA/stack_and_queue'
4
+ require_relative 'DSA/list'
5
+ require_relative 'DSA/priority_queue'
6
+ require_relative 'DSA/binary_search_tree'
7
+
8
+ module DSA
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,69 @@
1
+ module DSA
2
+ module Algorithm
3
+
4
+ # Factorial function, the "Hello World" program of recursion
5
+ def self.factorial(n)
6
+ if n == 0
7
+ 1
8
+ else
9
+ n * factorial(n-1)
10
+ end
11
+ end
12
+
13
+
14
+ # Binary search in sorted array
15
+ def self.binary_search(data, target, low, high)
16
+ return false if low > high
17
+ middle = (low + high) / 2
18
+ if data[middle] == target
19
+ true
20
+ elsif target < data[middle]
21
+ binary_search data, target, low, middle-1
22
+ else
23
+ binary_search data, target, middle+1, high
24
+ end
25
+ end
26
+
27
+ # Insertion sort, n square worst running time, should not be used in general, built-in array sort is very good
28
+ def self.insertion_sort!(data)
29
+ data.length.times do |index|
30
+ this_value = data[index]
31
+ j = index - 1
32
+ while j >= -1
33
+ if data[j] > this_value && j != -1
34
+ data[j+1] = data[j]
35
+ else
36
+ data[j+1] = this_value
37
+ break
38
+ end
39
+ j -= 1
40
+ end
41
+ end
42
+ end
43
+
44
+ # in place quick sort
45
+ def self.quick_sort!(data, low, high)
46
+ return if low >= high
47
+ pivot = data[high]
48
+ left = low
49
+ right = high - 1
50
+ while left <= right
51
+ until left > right || data[left] >= pivot
52
+ left += 1
53
+ end
54
+ until left > right || data[right] <= pivot
55
+ right -= 1
56
+ end
57
+ if left <= right
58
+ data[left], data[right] = data[right], data[left]
59
+ left += 1
60
+ right -= 1
61
+ end
62
+ end
63
+ data[left], data[high] = data[high], data[left]
64
+ quick_sort!(data, low, left - 1)
65
+ quick_sort!(data, left+1, high)
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,710 @@
1
+ module DSA
2
+ # A basic binary search tree node
3
+ class BasicBinarySearchTreeNode
4
+ attr_accessor :key, :value, :parent, :left, :right
5
+ def initialize(key, value)
6
+ @key = key
7
+ @value = value
8
+ @parent = nil
9
+ @left = nil
10
+ @right = nil
11
+ end
12
+ end
13
+ # A basic binary search tree(or ordered map), with no specific self balancing
14
+ class BasicBinarySearchTree
15
+ include Enumerable
16
+
17
+ def initialize
18
+ @root = nil
19
+ end
20
+
21
+ def []=(key, value)
22
+ new_node = BasicBinarySearchTreeNode.new(key, value)
23
+ if @root.nil?
24
+ @root = new_node
25
+ else
26
+ insert(@root, new_node)
27
+ end
28
+ end
29
+
30
+ def delete(key)
31
+ return nil if @root.nil?
32
+ node = find_node @root, key
33
+ return nil if node.nil?
34
+ delete_node(node).first.value
35
+ end
36
+
37
+ def [](key)
38
+ return nil if @root.nil?
39
+ node = find_node @root, key
40
+ if node
41
+ node.value
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ # yield the key/value pair for all those great than input key
48
+ def gt(key)
49
+ return nil if @root.nil?
50
+
51
+ if block_given?
52
+ node = find_gt_node @root, key
53
+ if node
54
+ yield [node.key, node.value]
55
+ loop do
56
+ node = in_order_next_node node
57
+ if node
58
+ yield [node.key, node.value]
59
+ else
60
+ break
61
+ end
62
+ end
63
+ end
64
+ else
65
+ Enumerator.new do |y|
66
+ gt(key) do |key, value|
67
+ y << [key, value]
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ end
74
+
75
+ # yield the key/value pair for all those less than input key
76
+ def lt(key)
77
+ return nil if @root.nil?
78
+
79
+ if block_given?
80
+ node = find_lt_node @root, key
81
+ if node
82
+ yield [node.key, node.value]
83
+ loop do
84
+ node = in_order_prev_node node
85
+ if node
86
+ yield [node.key, node.value]
87
+ else
88
+ break
89
+ end
90
+ end
91
+ end
92
+ else
93
+ Enumerator.new do |y|
94
+ lt(key) do |key, value|
95
+ y << [key, value]
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ # yield the key/value pair for all those great than or equal to input key
102
+ def ge(key)
103
+ return nil if @root.nil?
104
+
105
+ if block_given?
106
+ node = find_node @root, key
107
+ yield [node.key, node.value] if node
108
+ node = find_gt_node @root, key
109
+ if node
110
+ yield [node.key, node.value]
111
+ loop do
112
+ node = in_order_next_node node
113
+ if node
114
+ yield [node.key, node.value]
115
+ else
116
+ break
117
+ end
118
+ end
119
+ end
120
+ else
121
+ Enumerator.new do |y|
122
+ ge(key) do |key, value|
123
+ y << [key, value]
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ # yield the key/value pair for all those great than or equal to input key
130
+ def le(key)
131
+ return nil if @root.nil?
132
+
133
+ if block_given?
134
+ node = find_node @root, key
135
+ yield [node.key, node.value] if node
136
+ node = find_lt_node @root, key
137
+ if node
138
+ yield [node.key, node.value]
139
+ loop do
140
+ node = in_order_prev_node node
141
+ if node
142
+ yield [node.key, node.value]
143
+ else
144
+ break
145
+ end
146
+ end
147
+ end
148
+ else
149
+ Enumerator.new do |y|
150
+ le(key) do |key, value|
151
+ y << [key, value]
152
+ end
153
+ end
154
+ end
155
+
156
+ end
157
+
158
+
159
+ def each
160
+ return if @root.nil?
161
+ if block_given?
162
+ in_order_traversal @root, Proc.new
163
+ else
164
+ Enumerator.new do |y|
165
+ each do |key, value|
166
+ y << [key, value]
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ def min
173
+ if @root.nil?
174
+ nil
175
+ else
176
+ min_node(@root).value
177
+ end
178
+ end
179
+
180
+ def max
181
+ if @root.nil?
182
+ nil
183
+ else
184
+ max_node(@root).value
185
+ end
186
+ end
187
+
188
+ # breadth first traversal
189
+ def bfs_print
190
+ puts '=' * 100
191
+ level = [@root]
192
+ until level.empty?
193
+ next_level = []
194
+ level.each do |node|
195
+ if node
196
+ printf "<#{node.key}, #{node.value}>"
197
+ printf "(parent_is_#{node.parent.key})\t" if node != @root
198
+ next_level.push node.left
199
+ next_level.push node.right
200
+ else
201
+ printf "<Nil>\t"
202
+ next_level.push nil
203
+ next_level.push nil
204
+ end
205
+ end
206
+ puts
207
+ if next_level.count(nil) < next_level.length
208
+ level = next_level
209
+ else
210
+ level = []
211
+ end
212
+ end
213
+ puts '=' * 100
214
+ end
215
+
216
+ protected
217
+ def in_order_next_node(node)
218
+ # if it has a right subtree, take the left most of right subtree
219
+ if !node.right.nil?
220
+ return min_node node.right
221
+
222
+ # if it is a left child, take the parent
223
+ # if it is a right child, go up till we find a left child's parent, otherwise finished
224
+ else
225
+ while !node.nil?
226
+ return node.parent if left_child? node
227
+ node = node.parent
228
+ end
229
+ end
230
+
231
+ nil
232
+ end
233
+
234
+ def in_order_prev_node(node)
235
+ # if it has a left subtree, take the right most of left subtree
236
+ if !node.left.nil?
237
+ return max_node node.left
238
+
239
+ # if it is a right child, take the parent
240
+ # if it is a left child, go up till we find a right child's parent, otherwise finished
241
+ else
242
+ while !node.nil?
243
+ return node.parent if right_child? node
244
+ node = node.parent
245
+ end
246
+ end
247
+
248
+ nil
249
+ end
250
+
251
+ def left_child?(node)
252
+ parent = node.parent
253
+ if parent
254
+ parent.left == node
255
+ else
256
+ false
257
+ end
258
+ end
259
+
260
+ def right_child?(node)
261
+ parent = node.parent
262
+ if parent
263
+ parent.right == node
264
+ else
265
+ false
266
+ end
267
+ end
268
+
269
+
270
+ # in-order traversal
271
+ def in_order_traversal(node, block)
272
+ unless node.left.nil?
273
+ in_order_traversal(node.left, block)
274
+ end
275
+ block.call(node.key, node.value)
276
+ unless node.right.nil?
277
+ in_order_traversal(node.right, block)
278
+ end
279
+ end
280
+
281
+ def delete_node(node)
282
+ if node.left.nil? && node.right.nil? # it's a leaf
283
+ replace node, nil
284
+ elsif ! node.left.nil? && node.right.nil? # only has a left child
285
+ replace node, node.left
286
+ elsif node.left.nil? && ! node.right.nil? # only has a right child
287
+ replace node, node.right
288
+ else # has both children
289
+ next_node = min_node node.right
290
+ node.key = next_node.key
291
+ node.value = next_node.value
292
+ delete_node next_node
293
+ end
294
+ end
295
+
296
+ # replace a node with another node, this includes the links that node has
297
+ def replace(node, new_node)
298
+ if node == @root
299
+ @root = new_node
300
+ sibling = nil
301
+ else
302
+ parent = node.parent
303
+ if parent.left == node
304
+ parent.left = new_node
305
+ sibling = parent.right
306
+ else
307
+ parent.right = new_node
308
+ sibling = parent.left
309
+ end
310
+ new_node.parent = parent unless new_node.nil?
311
+ end
312
+ [node, new_node, sibling]
313
+ end
314
+
315
+
316
+ # find the minimum node of a subtree
317
+ def min_node(node)
318
+ if node.left.nil?
319
+ node
320
+ else
321
+ min_node node.left
322
+ end
323
+ end
324
+
325
+ # find the maximum node of a subtree
326
+ def max_node(node)
327
+ if node.right.nil?
328
+ node
329
+ else
330
+ max_node node.right
331
+ end
332
+ end
333
+
334
+ # find a node through a key in a subtree
335
+ def find_node(node, key)
336
+ if node.key == key
337
+ node
338
+ elsif key < node.key
339
+ if node.left
340
+ find_node node.left, key
341
+ else
342
+ nil
343
+ end
344
+ else
345
+ if node.right
346
+ find_node node.right, key
347
+ else
348
+ nil
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ # find first node that is greater than the key in a subtree
355
+ def find_gt_node(node, key)
356
+ if key == node.key
357
+ in_order_next_node node
358
+ elsif key < node.key
359
+ if node.left
360
+ find_gt_node node.left, key
361
+ else
362
+ node
363
+ end
364
+ else
365
+ if node.right
366
+ find_gt_node node.right, key
367
+ else
368
+ in_order_next_node node
369
+ end
370
+ end
371
+
372
+ end
373
+
374
+ # find first node that is less than the key in a subtree
375
+ def find_lt_node(node, key)
376
+ if key == node.key
377
+ in_order_prev_node node
378
+ elsif key < node.key
379
+ if node.left
380
+ find_lt_node node.left, key
381
+ else
382
+ in_order_prev_node node
383
+ end
384
+ else
385
+ if node.right
386
+ find_lt_node node.right, key
387
+ else
388
+ node
389
+ end
390
+ end
391
+
392
+ end
393
+
394
+ # insert a new node into the binary search (sub)tree
395
+ def insert(node, new_node)
396
+ if node.key == new_node.key
397
+ node.value = new_node.value
398
+ return node
399
+ elsif new_node.key < node.key
400
+ if node.left.nil?
401
+ node.left = new_node
402
+ new_node.parent = node
403
+ return new_node
404
+ else
405
+ insert( node.left, new_node )
406
+ end
407
+ else
408
+ if node.right.nil?
409
+ node.right = new_node
410
+ new_node.parent = node
411
+ return new_node
412
+ else
413
+ insert( node.right, new_node )
414
+ end
415
+ end
416
+ end
417
+
418
+ end
419
+
420
+ class RedBlackTreeNode < BasicBinarySearchTreeNode
421
+ RED = 0
422
+ BLACK = 1
423
+ def initialize(key, value)
424
+ super(key, value)
425
+ @color = RED
426
+ end
427
+
428
+ def red?
429
+ @color == RED
430
+ end
431
+
432
+ def black?
433
+ @color == BLACK
434
+ end
435
+
436
+ def set_black!
437
+ @color = BLACK
438
+ end
439
+
440
+ def set_red!
441
+ @color = RED
442
+ end
443
+ end
444
+
445
+ class RedBlackTree < BasicBinarySearchTree
446
+
447
+ def []=(key, value)
448
+ new_node = RedBlackTreeNode.new(key, value)
449
+ if @root.nil?
450
+ new_node.set_black!
451
+ @root = new_node
452
+ else
453
+ node = insert(@root, new_node)
454
+ fix_variance node if node.red? # when it is an existing node, it could be black
455
+ end
456
+ end
457
+
458
+ def delete(key)
459
+ return nil if @root.nil?
460
+ node = find_node @root, key
461
+ return nil if node.nil?
462
+ rb_delete_node(node).first.value
463
+ end
464
+
465
+ # breadth first traversal
466
+ def bfs_print
467
+ puts '=' * 100
468
+ level = [@root]
469
+ until level.empty?
470
+ next_level = []
471
+ level.each do |node|
472
+ if node
473
+ printf "<#{node.key}, #{node.value}>"
474
+ printf "(#{node.parent.key}|" if node != @root
475
+ if node.red?
476
+ printf "R)\t"
477
+ else
478
+ printf "B)\t"
479
+ end
480
+ next_level.push node.left
481
+ next_level.push node.right
482
+ else
483
+ printf "<Nil>\t"
484
+ next_level.push nil
485
+ next_level.push nil
486
+ end
487
+ end
488
+ puts
489
+ if next_level.count(nil) < next_level.length
490
+ level = next_level
491
+ else
492
+ level = []
493
+ end
494
+ end
495
+ puts '=' * 100
496
+ end
497
+
498
+ private
499
+ def rb_delete_node(node)
500
+ node, replace_node, sibling = delete_node(node)
501
+ value = [node, replace_node]
502
+
503
+ return value if node.red? # red is always fine
504
+ if node.black?
505
+ if replace_node # if it has a child(the replace_node), it must be red
506
+ replace_node.set_black!
507
+ else # it is a black leaf, it is complicated
508
+ fix_deficit sibling
509
+ end
510
+ end
511
+
512
+ value
513
+ end
514
+
515
+ # the heavier side after a black leaf deleted
516
+ def fix_deficit(sibling)
517
+ parent = sibling.parent
518
+ if sibling.black?
519
+ x = has_red_child? sibling
520
+ if x
521
+ deletion_restructure(x)
522
+ else # if sibling does not have a red child
523
+ sibling.set_red!
524
+ if parent.red?
525
+ parent.set_black!
526
+ else
527
+ fix_deficit sibling_of(parent)
528
+ end
529
+ end
530
+ else # when my sibling is red
531
+ if left_child? sibling
532
+ heavy_node = sibling.right
533
+ right_up_rotation sibling
534
+ else
535
+ heavy_node = sibling.left
536
+ left_up_rotation sibling
537
+ end
538
+ sibling.set_black!
539
+ parent.set_red!
540
+ fix_deficit heavy_node
541
+ end
542
+ end
543
+
544
+ def has_red_child?(node)
545
+ if node.left && node.left.red?
546
+ node.left
547
+ elsif node.right && node.right.red?
548
+ node.right
549
+ else
550
+ nil
551
+ end
552
+ end
553
+
554
+ def fix_variance(node)
555
+ # for root, recolor to black when necessary
556
+ if node == @root
557
+ node.set_black! if node.red?
558
+ return
559
+ end
560
+
561
+ parent = node.parent
562
+ return if parent.black? # we are good
563
+
564
+ # otherwise we have the double red
565
+ grand_parent = parent.parent
566
+ uncle = sibling_of parent
567
+
568
+ if uncle && uncle.red?
569
+ parent.set_black!
570
+ uncle.set_black!
571
+ grand_parent.set_red!
572
+ fix_variance grand_parent
573
+ else
574
+ restructure( node )
575
+ end
576
+
577
+ end
578
+
579
+ # rotations and re-color in different cases(zig-zig and zig-zag) for deletion
580
+ def deletion_restructure(node)
581
+ parent = node.parent
582
+ grand_parent = parent.parent
583
+ if left_child?(node) && left_child?(parent)
584
+ right_up_rotation parent
585
+ if grand_parent.red?
586
+ parent.set_red!
587
+ else
588
+ parent.set_black!
589
+ end
590
+ node.set_black!
591
+ grand_parent.set_black!
592
+ elsif right_child?(node) && left_child?(parent)
593
+ left_up_rotation node
594
+ right_up_rotation node
595
+ if grand_parent.red?
596
+ node.set_red!
597
+ else
598
+ node.set_black!
599
+ end
600
+ parent.set_black!
601
+ grand_parent.set_black!
602
+ elsif right_child?(node) && right_child?(parent)
603
+ left_up_rotation parent
604
+ if grand_parent.red?
605
+ parent.set_red!
606
+ else
607
+ parent.set_black!
608
+ end
609
+ node.set_black!
610
+ grand_parent.set_black!
611
+ else
612
+ right_up_rotation node
613
+ left_up_rotation node
614
+ if grand_parent.red?
615
+ node.set_red!
616
+ else
617
+ node.set_black!
618
+ end
619
+ parent.set_black!
620
+ grand_parent.set_black!
621
+ end
622
+ end
623
+
624
+ # rotations and re-color in different cases(zig-zig and zig-zag) for insertion
625
+ def restructure(node)
626
+ parent = node.parent
627
+ grand_parent = parent.parent
628
+ if left_child?(node) && left_child?(parent)
629
+ right_up_rotation parent
630
+ parent.set_black!
631
+ node.set_red!
632
+ grand_parent.set_red!
633
+ elsif right_child?(node) && left_child?(parent)
634
+ left_up_rotation node
635
+ right_up_rotation node
636
+ node.set_black!
637
+ parent.set_red!
638
+ grand_parent.set_red!
639
+ elsif right_child?(node) && right_child?(parent)
640
+ left_up_rotation parent
641
+ parent.set_black!
642
+ node.set_red!
643
+ grand_parent.set_red!
644
+ else
645
+ right_up_rotation node
646
+ left_up_rotation node
647
+ node.set_black!
648
+ parent.set_red!
649
+ grand_parent.set_red!
650
+ end
651
+ end
652
+
653
+ def sibling_of(node)
654
+ parent = node.parent
655
+ return nil if parent.nil?
656
+ if left_child? node
657
+ parent.right
658
+ else
659
+ parent.left
660
+ end
661
+ end
662
+
663
+ def right_up_rotation(node)
664
+ parent = node.parent
665
+ grand_parent = parent.parent
666
+
667
+ node.parent = grand_parent
668
+ if left_child? parent
669
+ grand_parent.left = node
670
+ elsif right_child? parent
671
+ grand_parent.right = node
672
+ else
673
+ @root = node
674
+ end
675
+
676
+ parent.left = node.right
677
+ node.right.parent = parent if node.right
678
+
679
+ node.right = parent
680
+ parent.parent = node
681
+
682
+ end
683
+
684
+ def left_up_rotation(node)
685
+ parent = node.parent
686
+ grand_parent = parent.parent
687
+
688
+ node.parent = grand_parent
689
+ if left_child? parent
690
+ grand_parent.left = node
691
+ elsif right_child? parent
692
+ grand_parent.right = node
693
+ else
694
+ @root = node
695
+ end
696
+
697
+ parent.right = node.left
698
+ node.left.parent = parent if node.left
699
+
700
+ node.left = parent
701
+ parent.parent = node
702
+
703
+ end
704
+
705
+
706
+ end
707
+
708
+ BinarySearchTree = RedBlackTree
709
+ OrderedMap = RedBlackTree
710
+ end