Skip to content

Commit 0dfe465

Browse files
committed
fix code, and add docstrings
1 parent 8ea8308 commit 0dfe465

File tree

3 files changed

+130
-62
lines changed

3 files changed

+130
-62
lines changed

src/DataStructures.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ module DataStructures
6161

6262
export DiBitVector
6363

64+
export AVLTree
65+
6466
export findkey
6567

6668
include("delegate.jl")

src/avl_tree.jl

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,18 @@ AVLTreeNode_or_null{T} = Union{AVLTreeNode{T}, Nothing}
1414

1515
mutable struct AVLTree{T}
1616
root::AVLTreeNode_or_null{T}
17+
count::Int
1718

18-
AVLTree{T}() where T = new{T}(nothing)
19+
AVLTree{T}() where T = new{T}(nothing, 0)
1920
end
2021

2122
AVLTree() = AVLTree{Any}()
2223

23-
function get_height(node::Union{AVLTreeNode, Nothing})
24-
if node == nothing
25-
return 0
26-
else
27-
return node.height
28-
end
29-
end
24+
Base.length(tree::AVLTree) = tree.count
25+
26+
get_height(node::Union{AVLTreeNode, Nothing}) = (node == nothing) ? 0 : node.height
3027

28+
# balance is the difference of height between leftChild and rightChild of a node.
3129
function get_balance(node::Union{AVLTreeNode, Nothing})
3230
if node == nothing
3331
return 0
@@ -36,8 +34,13 @@ function get_balance(node::Union{AVLTreeNode, Nothing})
3634
end
3735
end
3836

39-
fix_height(node::Union{AVLTreeNode, Nothing}) = 1 + max(get_height(node.leftChild), get_height(node.rightChild))
37+
fix_height(node::AVLTreeNode) = 1 + max(get_height(node.leftChild), get_height(node.rightChild))
38+
39+
"""
40+
left_rotate!(node_x::RBTreeNode)
4041
42+
Performs a left-rotation on `node_x`, updates height of the nodes, and returns the rotated node.
43+
"""
4144
function left_rotate(z::AVLTreeNode)
4245
y = z.rightChild
4346
α = y.leftChild
@@ -48,6 +51,11 @@ function left_rotate(z::AVLTreeNode)
4851
return y
4952
end
5053

54+
"""
55+
right_rotate!(node_x::RBTreeNode)
56+
57+
Performs a right-rotation on `node_x`, updates height of the nodes, and returns the rotated node.
58+
"""
5159
function right_rotate(z::AVLTreeNode)
5260
y = z.leftChild
5361
α = y.rightChild
@@ -58,17 +66,30 @@ function right_rotate(z::AVLTreeNode)
5866
return y
5967
end
6068

61-
function get_minimum_node(node::Union{AVLTreeNode, Nothing})
69+
"""
70+
minimum_node(tree::RBTree, node::RBTreeNode)
71+
72+
Returns the RBTreeNode with minimum value in subtree of `node`.
73+
"""
74+
function minimum_node(node::Union{AVLTreeNode, Nothing})
6275
while node != nothing && node.leftChild != nothing
6376
node = node.leftChild
6477
end
6578
return node
6679
end
6780

81+
"""
82+
search_node(tree, key)
83+
84+
Returns the last visited node, while traversing through in binary-search-tree fashion looking for `key`.
85+
"""
86+
search_node(tree, key)
87+
6888
function search_node(tree::AVLTree{K}, d::K) where K
6989
prev = nothing
7090
node = tree.root
7191
while node != nothing && node.data != nothing && node.data != d
92+
7293
prev = node
7394
if d < node.data
7495
node = node.leftChild
@@ -80,16 +101,30 @@ function search_node(tree::AVLTree{K}, d::K) where K
80101
return (node == nothing) ? prev : node
81102
end
82103

83-
function search_key(tree::AVLTree{K}, d::K) where K
104+
"""
105+
haskey(tree, key)
106+
107+
Returns true if `key` is present in the `tree`, else returns false.
108+
"""
109+
haskey(tree, key)
110+
111+
function haskey(tree::AVLTree{K}, d::K) where K
84112
(tree.root == nothing) && return false
85113
node = search_node(tree, d)
86114
return (node.data == d)
87115
end
88116

117+
"""
118+
insert!(tree, key)
119+
120+
Inserts `key` in the `tree` if it is not present.
121+
"""
122+
insert!(tree, key)
123+
89124
function Base.insert!(tree::AVLTree{K}, d::K) where K
90125

91126
function insert_node(node::Union{AVLTreeNode, Nothing}, key)
92-
if node == nothing || node.data == nothing
127+
if node == nothing
93128
return AVLTreeNode{K}(key)
94129
elseif key < node.data
95130
node.leftChild = insert_node(node.leftChild, key)
@@ -103,7 +138,7 @@ function Base.insert!(tree::AVLTree{K}, d::K) where K
103138
if balance > 1
104139
if key < node.leftChild.data
105140
return right_rotate(node)
106-
else
141+
107142
node.leftChild = left_rotate(node.leftChild)
108143
return right_rotate(node)
109144
end
@@ -113,20 +148,31 @@ function Base.insert!(tree::AVLTree{K}, d::K) where K
113148
if key > node.rightChild.data
114149
return left_rotate(node)
115150
else
116-
node.rightChild = right_rotate(node)
151+
node.rightChild = right_rotate(node.rightChild)
117152
return left_rotate(node)
118153
end
119154
end
120155

121156
return node
122157
end
123158

124-
search_key(tree, d) && return tree
159+
haskey(tree, d) && return tree
125160

126161
tree.root = insert_node(tree.root, d)
162+
tree.count += 1
127163
return tree
128164
end
129165

166+
"""
167+
push!(tree, key)
168+
169+
Inserts `key` in the `tree` if it is not present.
170+
"""
171+
function Base.push!(tree::AVLTree{K}, key0) where K
172+
key = convert(K, key0)
173+
insert!(tree, key)
174+
end
175+
130176
function Base.delete!(tree::AVLTree{K}, d::K) where K
131177

132178
function delete_node(node::Union{AVLTreeNode, Nothing}, key)
@@ -146,7 +192,7 @@ function Base.delete!(tree::AVLTree{K}, d::K) where K
146192
node = nothing
147193
return temp
148194
else
149-
temp = get_minimum_node(node.rightChild)
195+
temp = minimum_node(node.rightChild)
150196
node.data = temp.data
151197
node.rightChild = delete_node(node.rightChild, temp.data)
152198
end
@@ -180,8 +226,11 @@ function Base.delete!(tree::AVLTree{K}, d::K) where K
180226
return node
181227
end
182228

183-
!search_key(tree, d) && throw(KeyError(d))
229+
# if the key is not in the tree, do nothing and return the tree
230+
!haskey(tree, d) && return tree
184231

232+
# if the key is present, delete it from the tree
185233
tree.root = delete_node(tree.root, d)
234+
tree.count -= 1
186235
return tree
187-
end
236+
end

test/test_avl_tree.jl

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,78 @@
1-
include("../src/avl_tree.jl")
21
@testset "AVLTree" begin
3-
t = AVLTree()
4-
for i = 1:10000
5-
insert!(t, i)
6-
end
7-
for i = 1:10000
8-
@test search_key(t, i)
9-
end
2+
@testset "inserting values" begin
3+
t = AVLTree{Int}()
4+
for i in 1:100
5+
insert!(t, i)
6+
end
107

11-
for i = 10001:20000
12-
@test !search_key(t, i)
13-
end
8+
@test length(t) == 100
149

15-
for i = 1:2:10000
16-
delete!(t, i)
17-
end
10+
for i in 1:100
11+
@test haskey(t, i)
12+
end
1813

19-
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
14+
for i = 101:200
15+
@test !haskey(t, i)
16+
end
2617
end
2718

28-
for i = 1:2:1000
29-
insert!(t, i)
30-
end
19+
@testset "deleting values" begin
20+
t = AVLTree{Int}()
21+
for i in 1:100
22+
insert!(t, i)
23+
end
24+
for i in 1:2:100
25+
delete!(t, i)
26+
end
3127

32-
for i = 1:1000
33-
@test search_key(t, i)
34-
end
28+
@test length(t) == 50
29+
30+
for i in 1:100
31+
if iseven(i)
32+
@test haskey(t, i)
33+
else
34+
@test !haskey(t, i)
35+
end
36+
end
37+
38+
for i in 1:2:100
39+
insert!(t, i)
40+
end
3541

36-
# for handling cases related to delete!
37-
t2 = AVLTree{Int}()
38-
for i = 1:100000
39-
insert!(t2, i)
42+
@test length(t) == 100
4043
end
4144

42-
nums = rand(1:100000, 1000)
43-
visited = Set{Int}()
44-
for num in nums
45-
if num in visited
46-
@test_throws KeyError delete!(t2, num)
47-
else
48-
delete!(t2, num)
49-
push!(visited, num)
45+
@testset "handling different cases of delete!" begin
46+
t2 = AVLTree()
47+
for i in 1:100000
48+
insert!(t2, i)
49+
end
50+
51+
@test length(t2) == 100000
52+
53+
nums = rand(1:100000, 8599)
54+
visited = Set()
55+
for num in nums
56+
if !(num in visited)
57+
delete!(t2, num)
58+
push!(visited, num)
59+
end
60+
end
61+
62+
for i in visited
63+
@test !haskey(t2, i)
5064
end
65+
@test (length(t2) + length(visited)) == 100000
5166
end
5267

53-
for i = 1:100000
54-
if i in visited
55-
@test !search_key(t2, i)
56-
else
57-
@test search_key(t2, i)
68+
@testset "handling different cases of insert!" begin
69+
nums = rand(1:100000, 1000)
70+
t3 = AVLTree()
71+
uniq_nums = Set(nums)
72+
for num in uniq_nums
73+
insert!(t3, num)
5874
end
75+
@test length(t3) == length(uniq_nums)
5976
end
6077

6178
end

0 commit comments

Comments
 (0)