-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathred_black_bst.rb
137 lines (106 loc) · 2.57 KB
/
red_black_bst.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
class Node
attr_accessor :key, :value, :left, :right, :color, :size, :same
def initialize(key, value, color)
@key = key
@value = value
@color = color
@size = 1
@same = 0
end
end
class IntComparator
def self.compare(key1, key2)
if key1 < key2
return -1
elsif key1 > key2
return 1
else
return 0
end
end
end
class RedBlackBST
RED = true
BLACK = false
def initialize(comparator)
@comparator = comparator
end
# return number of keys less than given
def treeRank(key)
rank(key, @root)
end
def treeSize
size @root
end
def put(key, value = nil)
@count = 0
@root = putToNode(@root, key, value)
@root.color = RED
@count
end
private
def isRed(node)
return false if node.nil?
node.color == RED
end
def putToNode(node, key, value)
return Node.new(key, value, RED) if node.nil?
cmp = @comparator.compare(key, node.key)
if cmp < 0
@count += 1 + node.same() + size(node.right)
node.left = putToNode(node.left, key, value)
elsif cmp > 0
node.right = putToNode(node.right, key, value)
else
node.value = value
node.same += 1
@count += size(node.right)
end
node = rotateLeft(node) if isRed(node.right) && !isRed(node.left)
node = rotateRight(node) if isRed(node.left) && isRed(node.left.left)
flipColors(node) if isRed(node.left) && isRed(node.right)
node.size = size(node.left) + size(node.right) + 1
node
end
def rotateLeft(node)
newNode = node.right
node.right = newNode.left
newNode.left = node
newNode.color = newNode.left.color
newNode.left.color = RED
newNode.size = size(newNode)
node.size = size(node.left) + size(node.right) + 1
newNode
end
def rotateRight(node)
newNode = node.left
node.left = newNode.right
newNode.right = node
newNode.color = node.color
node.color = RED
newNode.size = size(newNode)
node.size = size(node.left) + size(node.right) + 1
newNode
end
def flipColors(node)
node.color = !node.color
node.left.color = !node.left.color
node.right.color = !node.right.color
end
def size(node)
return 0 if node.nil?
node.size() + node.same()
end
# return number of keys less than key in subtree at node
def rank(key, node)
return 0 if node.nil?
cmp = @comparator.compare(key, node.key)
if cmp < 0
return rank(key, node.left)
elsif cmp > 0
return 1 + node.same() + size(node.left) + rank(key, node.right)
else
return size(node.left)
end
end
end