Skip to content

Commit fe1ebd9

Browse files
committed
Address review
1 parent bdc2213 commit fe1ebd9

File tree

2 files changed

+99
-40
lines changed

2 files changed

+99
-40
lines changed

src/red_black_tree.jl

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ end
2323

2424
Base.:(==)(x::RBTreeNode{K}, y::RBTreeNode{K}) where K = isequal(x, y)
2525

26-
Base.:(!=)(x::RBTreeNode{K}, y::RBTreeNode{K}) where K = !isequal(x, y)
26+
Base.hash(x::RBTreeNode) = hash(x.data, hash(x.color))
2727

2828
function create_null_node(K::Type)
2929
node = RBTreeNode{K}()
@@ -33,7 +33,7 @@ end
3333

3434
mutable struct RBTree{K}
3535
root::RBTreeNode{K}
36-
Nil::RBTreeNode{K}
36+
nil::RBTreeNode{K}
3737

3838
function RBTree{K}() where K
3939
new{K}(create_null_node(K), create_null_node(K))
@@ -42,9 +42,16 @@ end
4242

4343
RBTree() = RBTree{Any}()
4444

45+
"""
46+
search_node(tree, key)
47+
48+
Returns the last visited node, while traversing through in binary-search-tree fashion looking for `key`.
49+
"""
50+
search_node(tree, key)
51+
4552
function search_node(tree::RBTree{K}, d::K) where K
4653
node = tree.root
47-
while node != tree.Nil && d != node.data
54+
while node != tree.nil && d != node.data
4855
if d < node.data
4956
node = node.leftChild
5057
else
@@ -54,16 +61,28 @@ function search_node(tree::RBTree{K}, d::K) where K
5461
return node
5562
end
5663

64+
"""
65+
search_key(tree, key)
66+
67+
Returns true if `key` is present in the `tree`, else returns false.
68+
"""
69+
search_key(tree, key)
70+
5771
function search_key(tree::RBTree{K}, d::K) where K
5872
node = search_node(tree, d)
5973
return (node.data == d)
6074
end
6175

76+
"""
77+
insert_node!(tree::RBTree, node::RBTreeNode)
78+
79+
Inserts `node` at proper location by traversing through the `tree` in a binary-search-tree fashion.
80+
"""
6281
function insert_node!(tree::RBTree, node::RBTreeNode)
6382
node_y = nothing
6483
node_x = tree.root
6584

66-
while node_x != tree.Nil
85+
while node_x != tree.nil
6786
node_y = node_x
6887
if node.data < node_x.data
6988
node_x = node_x.leftChild
@@ -82,10 +101,15 @@ function insert_node!(tree::RBTree, node::RBTreeNode)
82101
end
83102
end
84103

104+
"""
105+
left_rotate!(tree::RBTree, node_x::RBTreeNode)
106+
107+
Performs a left-rotation on `node_x` and updates `tree.root`, if required.
108+
"""
85109
function left_rotate!(tree::RBTree, node_x::RBTreeNode)
86110
node_y = node_x.rightChild
87111
node_x.rightChild = node_y.leftChild
88-
if node_y.leftChild != tree.Nil
112+
if node_y.leftChild != tree.nil
89113
node_y.leftChild.parent = node_x
90114
end
91115
node_y.parent = node_x.parent
@@ -100,10 +124,15 @@ function left_rotate!(tree::RBTree, node_x::RBTreeNode)
100124
node_x.parent = node_y
101125
end
102126

127+
"""
128+
right_rotate!(tree::RBTree, node_x::RBTreeNode)
129+
130+
Performs a right-rotation on `node_x` and updates `tree.root`, if required.
131+
"""
103132
function right_rotate!(tree::RBTree, node_x::RBTreeNode)
104133
node_y = node_x.leftChild
105134
node_x.leftChild = node_y.rightChild
106-
if node_y.rightChild != tree.Nil
135+
if node_y.rightChild != tree.nil
107136
node_y.rightChild.parent = node_x
108137
end
109138
node_y.parent = node_x.parent
@@ -118,6 +147,11 @@ function right_rotate!(tree::RBTree, node_x::RBTreeNode)
118147
node_x.parent = node_y
119148
end
120149

150+
"""
151+
fix_insert!(tree::RBTree, node::RBTreeNode)
152+
153+
This method is called to fix the property of having no two adjacent nodes of red color in the `tree`.
154+
"""
121155
function fix_insert!(tree::RBTree, node::RBTreeNode)
122156
parent = nothing
123157
grand_parent = nothing
@@ -128,20 +162,16 @@ function fix_insert!(tree::RBTree, node::RBTreeNode)
128162
parent = node.parent
129163
grand_parent = parent.parent
130164

131-
# parent is the leftChild of grand_parent
132-
if (parent == grand_parent.leftChild)
165+
if (parent == grand_parent.leftChild) # parent is the leftChild of grand_parent
133166
uncle = grand_parent.rightChild
134167

135-
# uncle is red in color
136-
if (uncle.color)
168+
if (uncle.color) # uncle is red in color
137169
grand_parent.color = true
138170
parent.color = false
139171
uncle.color = false
140172
node = grand_parent
141-
# uncle is black in color
142-
else
143-
# node is rightChild of it's parent
144-
if (node == parent.rightChild)
173+
else # uncle is black in color
174+
if (node == parent.rightChild) # node is rightChild of it's parent
145175
node = parent
146176
left_rotate!(tree, node)
147177
end
@@ -150,20 +180,16 @@ function fix_insert!(tree::RBTree, node::RBTreeNode)
150180
node.parent.parent.color = true
151181
right_rotate!(tree, node.parent.parent)
152182
end
153-
# parent is the rightChild of grand_parent
154-
else
183+
else # parent is the rightChild of grand_parent
155184
uncle = grand_parent.leftChild
156185

157-
# uncle is red in color
158-
if (uncle.color)
186+
if (uncle.color) # uncle is red in color
159187
grand_parent.color = true
160188
parent.color = false
161189
uncle.color = false
162190
node = grand_parent
163-
# uncle is black in color
164-
else
165-
# node is leftChild of it's parent
166-
if (node == parent.leftChild)
191+
else # uncle is black in color
192+
if (node == parent.leftChild) # node is leftChild of it's parent
167193
node = parent
168194
right_rotate!(tree, node)
169195
end
@@ -177,14 +203,20 @@ function fix_insert!(tree::RBTree, node::RBTreeNode)
177203
tree.root.color = false
178204
end
179205

206+
"""
207+
insert!(tree, key)
208+
209+
Inserts `key` in the `tree` if it is not present.
210+
"""
211+
insert!(tree, key)
180212

181213
function Base.insert!(tree::RBTree{K}, d::K) where K
182214
# if the key exists in the tree, no need to insert
183215
search_key(tree, d) && return tree
184216
# search_key(tree, d) && return tree
185217
# insert, if not present in the tree
186218
node = RBTreeNode{K}(d)
187-
node.leftChild = node.rightChild = tree.Nil
219+
node.leftChild = node.rightChild = tree.nil
188220

189221
insert_node!(tree, node)
190222

@@ -198,6 +230,11 @@ function Base.insert!(tree::RBTree{K}, d::K) where K
198230
return tree
199231
end
200232

233+
"""
234+
delete_fix(tree::RBTree, node::Union{RBTreeNode, Nothing})
235+
236+
This method is called when a black node is deleted because it violates the black depth property of the RBTree.
237+
"""
201238
function delete_fix(tree::RBTree, node::Union{RBTreeNode, Nothing})
202239
while node != tree.root && !node.color
203240
if node == node.parent.leftChild
@@ -255,10 +292,14 @@ function delete_fix(tree::RBTree, node::Union{RBTreeNode, Nothing})
255292
end
256293
end
257294
node.color = false
258-
return tree
295+
return nothing
259296
end
260297

261-
# transplant u in the tree by v
298+
"""
299+
rb_transplant(tree::RBTree, u::Union{RBTreeNode, Nothing}, v::Union{RBTreeNode, Nothing})
300+
301+
Replaces `u` by `v` in the `tree` and updates the `tree` accordingly.
302+
"""
262303
function rb_transplant(tree::RBTree, u::Union{RBTreeNode, Nothing}, v::Union{RBTreeNode, Nothing})
263304
if u.parent == nothing
264305
tree.root = v
@@ -270,18 +311,30 @@ function rb_transplant(tree::RBTree, u::Union{RBTreeNode, Nothing}, v::Union{RBT
270311
v.parent = u.parent
271312
end
272313

314+
"""
315+
minimum_node(tree::RBTree, node::RBTreeNode)
316+
317+
Returns the RBTreeNode with minimum value in subtree of `node`.
318+
"""
273319
function minimum_node(tree::RBTree, node::RBTreeNode)
274-
while node.leftChild != tree.Nil
320+
while node.leftChild != tree.nil
275321
node = node.leftChild
276322
end
277323
return node
278324
end
279325

326+
"""
327+
delete!(tree::RBTree, key)
328+
329+
Deletes `key` from `tree`, if present, else throws a KeyError.
330+
"""
331+
delete!(tree, key)
332+
280333
function Base.delete!(tree::RBTree{K}, d::K) where K
281-
z = tree.Nil
334+
z = tree.nil
282335
node = tree.root
283336

284-
while node != tree.Nil
337+
while node != tree.nil
285338
if node.data == d
286339
z = node
287340
end
@@ -293,15 +346,15 @@ function Base.delete!(tree::RBTree{K}, d::K) where K
293346
end
294347
end
295348

296-
(z == tree.Nil) && throw(KeyError(d))
349+
(z == tree.nil) && throw(KeyError(d))
297350

298351
y = z
299352
y_original_color = y.color
300353
x = RBTreeNode{K}()
301-
if z.leftChild == tree.Nil
354+
if z.leftChild == tree.nil
302355
x = z.rightChild
303356
rb_transplant(tree, z, z.rightChild)
304-
elseif z.rightChild == tree.Nil
357+
elseif z.rightChild == tree.nil
305358
x = z.leftChild
306359
rb_transplant(tree, z, z.leftChild)
307360
else

test/test_red_black_tree.jl

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,27 @@ include("../src/red_black_tree.jl")
22
@testset "RBTree" begin
33
t = RBTree{Int}()
44
for i = 1:10000
5-
insert!(t, i)
5+
insert!(t, i)
66
end
77
for i = 1:10000
8-
@test search_key(t, i)
8+
@test search_key(t, i)
99
end
1010

1111
for i = 10001:20000
1212
@test !search_key(t, i)
1313
end
1414

1515
for i = 1:2:10000
16-
delete!(t, i)
16+
delete!(t, i)
1717
end
1818

1919
for i = 1:10000
20-
if iseven(i)
21-
@test search_key(t, i)
22-
else
23-
@test !search_key(t, i)
24-
@test_throws KeyError delete!(t, i)
25-
end
20+
if iseven(i)
21+
@test search_key(t, i)
22+
else
23+
@test !search_key(t, i)
24+
@test_throws KeyError delete!(t, i)
25+
end
2626
end
2727

2828
for i = 1:2:1000
@@ -33,6 +33,12 @@ include("../src/red_black_tree.jl")
3333
@test search_key(t, i)
3434
end
3535

36+
# test hash
37+
for i = 1:1000
38+
node = search_node(t, i)
39+
@test hash(node) == hash(i, hash(node.color))
40+
end
41+
3642
# for handling cases related to delete!
3743
t2 = RBTree()
3844
for i = 1:100000

0 commit comments

Comments
 (0)