Skip to content

Commit 0b3110c

Browse files
authored
Update search implementation & Add type stability tests (#9)
* Update search implementation & Add type stability tests * Update tests * Update comments
1 parent b38360e commit 0b3110c

File tree

2 files changed

+101
-26
lines changed

2 files changed

+101
-26
lines changed

src/avl.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ AVLNode(key, value) = AVLNode(key, value, 1, nothing, nothing)
1515
Base.convert(::Type{AVLNode{K,V}}, node::AVLNode) where {K,V} =
1616
AVLNode{K,V}(node.key, node.value, node.height, node.left, node.right)
1717

18+
Base.convert(::Type{AVLNode{K,V}}, node::AVLNode{K,V}) where {K,V} = node
19+
1820
# ---------
1921
# AVL TREE
2022
# ---------
@@ -29,8 +31,7 @@ and values of type `V`.
2931
3032
Construct an empty AVL tree with no values and keys of type `K`.
3133
32-
The keys of AVL Tree must implement sorting operators (`>`, `<`)
33-
and comparison operators (`=`, `≠`)
34+
The keys of AVL Tree must implement ordering relations (`>`, `<`).
3435
3536
# Examples
3637
@@ -88,10 +89,16 @@ end
8889

8990
function _search(tree, key)
9091
node = tree.root
91-
while !isnothing(node) && key node.key
92-
node = key < node.key ? node.left : node.right
92+
while !isnothing(node)
93+
if key < node.key
94+
node = node.left
95+
elseif key > node.key
96+
node = node.right
97+
else
98+
return node
99+
end
93100
end
94-
node
101+
nothing
95102
end
96103

97104
function _insert!(root, key, value)

test/runtests.jl

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,24 @@ const BT = BinaryTrees
66

77
@testset "BT.jl" begin
88
@testset "AVLTree" begin
9-
# insert
9+
# internal node conversion
10+
node1 = BT.AVLNode(1, 2)
11+
node2 = convert(BT.AVLNode{Float64,Float64}, node1)
12+
@test node2 isa BT.AVLNode{Float64,Float64}
13+
@test BT.key(node2) == 1.0
14+
@test BT.value(node2) == 2.0
15+
node3 = convert(typeof(node1), node1)
16+
@test node3 === node1
17+
18+
# insert & search
1019
tree = AVLTree{Int,Int}()
1120
BT.insert!(tree, 2, 20)
1221
BT.insert!(tree, 1, 10)
1322
BT.insert!(tree, 3, 30)
1423
@test BT.value(BT.search(tree, 2)) == 20
1524
@test BT.value(BT.search(tree, 1)) == 10
1625
@test BT.value(BT.search(tree, 3)) == 30
17-
18-
# value conversion
19-
tree = AVLTree{Int,Float64}()
20-
BT.insert!(tree, 2, 20)
21-
BT.insert!(tree, 1, 10)
22-
BT.insert!(tree, 3, 30)
23-
@test BT.value(BT.search(tree, 2)) isa Float64
24-
@test BT.value(BT.search(tree, 2)) == 20.0
25-
@test BT.value(BT.search(tree, 1)) isa Float64
26-
@test BT.value(BT.search(tree, 1)) == 10.0
27-
@test BT.value(BT.search(tree, 3)) isa Float64
28-
@test BT.value(BT.search(tree, 3)) == 30.0
26+
@test isnothing(BT.search(tree, 4))
2927

3028
# update values
3129
tree = AVLTree{Int,Int}()
@@ -42,7 +40,19 @@ const BT = BinaryTrees
4240
@test BT.value(BT.search(tree, 1)) == 11
4341
@test BT.value(BT.search(tree, 3)) == 33
4442

45-
# right rotate
43+
# value conversion
44+
tree = AVLTree{Int,Float64}()
45+
BT.insert!(tree, 2, 20)
46+
BT.insert!(tree, 1, 10)
47+
BT.insert!(tree, 3, 30)
48+
@test BT.value(BT.search(tree, 2)) isa Float64
49+
@test BT.value(BT.search(tree, 2)) == 20.0
50+
@test BT.value(BT.search(tree, 1)) isa Float64
51+
@test BT.value(BT.search(tree, 1)) == 10.0
52+
@test BT.value(BT.search(tree, 3)) isa Float64
53+
@test BT.value(BT.search(tree, 3)) == 30.0
54+
55+
# insert: right rotate
4656
tree = AVLTree{Int,Int}()
4757
BT.insert!(tree, 3, 30)
4858
BT.insert!(tree, 2, 20)
@@ -51,7 +61,7 @@ const BT = BinaryTrees
5161
@test tree |> BT.root |> BT.left |> BT.key == 1
5262
@test tree |> BT.root |> BT.right |> BT.key == 3
5363

54-
# left rotate
64+
# insert: left rotate
5565
tree = AVLTree{Int,Int}()
5666
BT.insert!(tree, 1, 10)
5767
BT.insert!(tree, 2, 20)
@@ -60,7 +70,7 @@ const BT = BinaryTrees
6070
@test tree |> BT.root |> BT.left |> BT.key == 1
6171
@test tree |> BT.root |> BT.right |> BT.key == 3
6272

63-
# left-right rotate
73+
# insert: left-right rotate
6474
tree = AVLTree{Int,Int}()
6575
BT.insert!(tree, 3, 30)
6676
BT.insert!(tree, 1, 10)
@@ -69,7 +79,7 @@ const BT = BinaryTrees
6979
@test tree |> BT.root |> BT.left |> BT.key == 1
7080
@test tree |> BT.root |> BT.right |> BT.key == 3
7181

72-
# right-left rotate
82+
# insert: right-left rotate
7383
tree = AVLTree{Int,Int}()
7484
BT.insert!(tree, 1, 10)
7585
BT.insert!(tree, 3, 30)
@@ -98,7 +108,7 @@ const BT = BinaryTrees
98108
BT.delete!(tree, 2)
99109
@test isnothing(BT.root(tree))
100110

101-
# right rotate
111+
# delete: right rotate
102112
tree = AVLTree{Int,Int}()
103113
BT.insert!(tree, 3, 30)
104114
BT.insert!(tree, 2, 20)
@@ -109,7 +119,7 @@ const BT = BinaryTrees
109119
@test tree |> BT.root |> BT.left |> BT.key == 1
110120
@test tree |> BT.root |> BT.right |> BT.key == 3
111121

112-
# left rotate
122+
# delete: left rotate
113123
tree = AVLTree{Int,Int}()
114124
BT.insert!(tree, 1, 10)
115125
BT.insert!(tree, -10, 0)
@@ -120,7 +130,7 @@ const BT = BinaryTrees
120130
@test tree |> BT.root |> BT.left |> BT.key == 1
121131
@test tree |> BT.root |> BT.right |> BT.key == 3
122132

123-
# left-right rotate
133+
# delete: left-right rotate
124134
tree = AVLTree{Int,Int}()
125135
BT.insert!(tree, 3, 30)
126136
BT.insert!(tree, 1, 10)
@@ -131,7 +141,7 @@ const BT = BinaryTrees
131141
@test tree |> BT.root |> BT.left |> BT.key == 1
132142
@test tree |> BT.root |> BT.right |> BT.key == 3
133143

134-
# right-left rotate
144+
# delete: right-left rotate
135145
tree = AVLTree{Int,Int}()
136146
BT.insert!(tree, 1, 10)
137147
BT.insert!(tree, -10, 0)
@@ -193,6 +203,64 @@ const BT = BinaryTrees
193203
BT.delete!(tree, 2)
194204
@test isnothing(BT.root(tree))
195205

206+
# tree with keys that implement ordering relations
207+
tree = AVLTree{String,Int}()
208+
BT.insert!(tree, "key2", 2)
209+
BT.insert!(tree, "key1", 1)
210+
BT.insert!(tree, "key3", 3)
211+
@test BT.value(BT.search(tree, "key2")) == 2
212+
@test BT.value(BT.search(tree, "key1")) == 1
213+
@test BT.value(BT.search(tree, "key3")) == 3
214+
tree = AVLTree{NTuple{3,Int},Int}()
215+
BT.insert!(tree, (0, 1, 0), 2)
216+
BT.insert!(tree, (0, 0, 1), 1)
217+
BT.insert!(tree, (1, 0, 0), 3)
218+
@test BT.value(BT.search(tree, (0, 1, 0))) == 2
219+
@test BT.value(BT.search(tree, (0, 0, 1))) == 1
220+
@test BT.value(BT.search(tree, (1, 0, 0))) == 3
221+
222+
# type stability
223+
tree = AVLTree{Int,Int}()
224+
@inferred BT.insert!(tree, 2, 20)
225+
@inferred BT.insert!(tree, 1, 10)
226+
@inferred BT.insert!(tree, 3, 30)
227+
@inferred Nothing BT.search(tree, 2)
228+
@inferred Nothing BT.search(tree, 1)
229+
@inferred Nothing BT.search(tree, 3)
230+
@inferred BT.delete!(tree, 2)
231+
@inferred BT.delete!(tree, 1)
232+
@inferred BT.delete!(tree, 3)
233+
tree = AVLTree{Int}()
234+
@inferred BT.insert!(tree, 2)
235+
@inferred BT.insert!(tree, 1)
236+
@inferred BT.insert!(tree, 3)
237+
@inferred Nothing BT.search(tree, 2)
238+
@inferred Nothing BT.search(tree, 1)
239+
@inferred Nothing BT.search(tree, 3)
240+
@inferred BT.delete!(tree, 2)
241+
@inferred BT.delete!(tree, 1)
242+
@inferred BT.delete!(tree, 3)
243+
tree = AVLTree{String,Int}()
244+
@inferred BT.insert!(tree, "key2", 2)
245+
@inferred BT.insert!(tree, "key1", 1)
246+
@inferred BT.insert!(tree, "key3", 3)
247+
@inferred Nothing BT.search(tree, "key2")
248+
@inferred Nothing BT.search(tree, "key1")
249+
@inferred Nothing BT.search(tree, "key3")
250+
@inferred BT.delete!(tree, "key2")
251+
@inferred BT.delete!(tree, "key1")
252+
@inferred BT.delete!(tree, "key3")
253+
tree = AVLTree{NTuple{3,Int},Int}()
254+
@inferred BT.insert!(tree, (0, 1, 0), 2)
255+
@inferred BT.insert!(tree, (0, 0, 1), 1)
256+
@inferred BT.insert!(tree, (1, 0, 0), 3)
257+
@inferred Nothing BT.search(tree, (0, 1, 0))
258+
@inferred Nothing BT.search(tree, (0, 0, 1))
259+
@inferred Nothing BT.search(tree, (1, 0, 0))
260+
@inferred BT.delete!(tree, (0, 1, 0))
261+
@inferred BT.delete!(tree, (0, 0, 1))
262+
@inferred BT.delete!(tree, (1, 0, 0))
263+
196264
# AbstractTrees interface
197265
tree = AVLTree{Int,Int}()
198266
BT.insert!(tree, 3, 30)

0 commit comments

Comments
 (0)