This repository was archived by the owner on Apr 13, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrbtree.rb
More file actions
195 lines (168 loc) · 5 KB
/
rbtree.rb
File metadata and controls
195 lines (168 loc) · 5 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# vim: tabstop=2 shiftwidth=2 softtabstop=2
=begin
= For recall a red-black tree has the following properties:
= 1. All nodes are either BLACK or RED
= 2. Leafs are BLACK
= 3. A RED node has BLACK children only
= 4. Path from a node to any leafs has the same number of BLACK nodes.
=end
require 'template_tree'
class RedBlackTreeNode < TemplateTreeNode
def red?
@red
end
def black?
not @red
end
def initialize(parent, key)
super
@red = true # we will make root black later, ok?
end
attr_writer :red # only writer, cause i have defined red? and black? (i think, it's really cool ^^ )
end
class RedBlackTree < TemplateTree
def insert(key = nil)
node, havent_inserted = super
return node if havent_inserted
# Fixup the modified tree by recoloring nodes and perfoming rotations (2 at most)
# hence the red-black properties are preserved
#
# The node we've inserted is red if it's not root
# So, we must perform some fixups only if its parent is red
while ((parent = node.parent) and parent.red?) do
grandpa = parent.parent #should always exists if we've assumed, that root is always BLACK
lp = (grandpa.left == parent)
uncle = if lp then grandpa.right
else grandpa.left
end
if uncle and uncle.red? then # if uncle is red
parent.red = false
uncle.red = false
grandpa.red = true
node = grandpa
else
lc = (parent.left == node)
unless lc == lp
# grandpa grandpa grandpa
# parent uncle => node uncle === rename === parent uncle
# a node b c parent .. ...... node ........
if lc then
rotate_right parent
else
rotate_left parent
end
node = parent
parent = node.parent
end
#now our node and its parent are both right (or left) childs
parent.red = false
grandpa.red = true
if lc then
rotate_right grandpa
else
rotate_left grandpa
end
end
end
@root.red = false
end
def remove(key = nil)
raise "Empty key" unless key
#search for node to delete
node = lookup key
return unless node
parent = node.parent
right = node.right
left = node.left
@first = node.next if @first.equal? node
@last = node.prev if @last.equal? node
_next = if not left then
right
elsif not right then
left
else
right.first
end
if not parent then @root = _next
elsif parent.left == node then parent.left = _next
else parent.right = _next
end
if left and right then
red, _next.red = _next.red?, node.red?
_next.left, left.parent = left, _next
unless _next == right then
parent, _next.parent = _next.parent, node.parent
node = _next.right
parent.left = node
_next.right = right
right.parent = _next
else
_next.parent = parent
parent = _next
node = _next.right
end
else
red = node.red?
node = _next
end
node.parent = parent if node
return if red
if node and node.red? then
node.red = false
return
end
begin
break if @root == node
lc = (parent.left == node)
sibling = if lc then parent.right
else parent.left
end
if sibling.red? then
sibling.red = false
parent.red = true
sibling = if lc then
rotate_left parent
parent.right
else
rotate_right parent
parent.left
end
end
if (lc and ((not sibling.right) or sibling.right.black?)) or
(not lc and ((not sibling.left) or sibling.left.black?)) then
sibling.red = true
if (not lc and ((not sibling.right) or sibling.right.black?)) or
(lc and ((not sibling.left) or sibling.left.black?)) then
node = parent
parent = node.parent
next
end
sibling = if lc then
sibling.left.red = false
rotate_right sibling
parent.right
else
sibling.right.red = false
rotate_left sibling
parent.left
end
end
sibling.red = parent.red?
parent.red = false
if lc then
sibling.right.red = false
rotate_left parent
else
sibling.left.red = false
rotate_right parent
end
node = @root
break
end while node.black?
node.red = false if node
end
def initialize
super
@NODECLASS = ::RedBlackTreeNode
end
end