Skip to content

Commit f8c0240

Browse files
authored
Add the BinaryTree interface (#6)
* Add the 'BinaryTree' interface * Add more docstrings & Add 'root' function
1 parent cf773ac commit f8c0240

File tree

5 files changed

+303
-225
lines changed

5 files changed

+303
-225
lines changed

README.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ An AVL tree is a binary search tree that keeps itself balanced to ensure efficie
2727
```julia
2828
tree = AVLTree{Int,Float64}()
2929

30-
# add nodes to the tree
31-
tree[2] = 2.2 # root node
32-
tree[1] = 1.1 # left node
33-
tree[3] = 3.3 # right node
30+
# insert nodes into the tree
31+
BinaryTrees.insert!(tree, 2, 2.2) # root node
32+
BinaryTrees.insert!(tree, 1, 1.1) # left node
33+
BinaryTrees.insert!(tree, 3, 3.3) # right node
3434

3535
# update the value of the node
36-
tree[2] = 2.4
36+
BinaryTrees.insert!(tree, 2, 2.4)
3737

38-
# get the value of the node using its key
39-
tree[2] # 2.4
40-
tree[1] # 1.1
41-
tree[3] # 3.3
38+
# search for nodes using their keys
39+
BinaryTrees.search(tree, 2) # root node
40+
BinaryTrees.search(tree, 1) # left node
41+
BinaryTrees.search(tree, 3) # right node
4242

4343
# delete nodes from the tree
44-
delete!(tree, 1)
45-
delete!(tree, 3)
44+
BinaryTrees.delete!(tree, 1)
45+
BinaryTrees.delete!(tree, 3)
4646
```

src/BinaryTrees.jl

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module BinaryTrees
22

33
import AbstractTrees
44

5+
include("binarytree.jl")
56
include("avl.jl")
67

78
export AVLTree

src/avl.jl

+19-72
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,18 @@
22
# AVL NODE
33
# ---------
44

5-
mutable struct AVLNode{K,V}
5+
mutable struct AVLNode{K,V} <: BinaryNode
66
key::K
77
value::V
8+
height::Int
89
left::Union{AVLNode{K,V},Nothing}
910
right::Union{AVLNode{K,V},Nothing}
10-
height::Int
1111
end
1212

13-
AVLNode(key, value) = AVLNode(key, value, nothing, nothing, 1)
13+
AVLNode(key, value) = AVLNode(key, value, 1, nothing, nothing)
1414

1515
Base.convert(::Type{AVLNode{K,V}}, node::AVLNode) where {K,V} =
16-
AVLNode{K,V}(node.key, node.value, node.left, node.right, node.height)
17-
18-
function AbstractTrees.children(node::AVLNode)
19-
if !isnothing(node.left) && !isnothing(node.right)
20-
(node.left, node.right)
21-
elseif !isnothing(node.left)
22-
(node.left,)
23-
elseif !isnothing(node.right)
24-
(node.right,)
25-
else
26-
()
27-
end
28-
end
29-
30-
AbstractTrees.NodeType(::Type{<:AVLNode}) = AbstractTrees.HasNodeType()
31-
AbstractTrees.nodetype(T::Type{<:AVLNode}) = T
32-
33-
function AbstractTrees.printnode(io::IO, node::AVLNode)
34-
ioctx = IOContext(io, :compact => true, :limit => true)
35-
show(ioctx, node.key)
36-
print(ioctx, " => ")
37-
show(ioctx, node.value)
38-
end
16+
AVLNode{K,V}(node.key, node.value, node.height, node.left, node.right)
3917

4018
# ---------
4119
# AVL TREE
@@ -60,74 +38,43 @@ and comparison operators (`=`, `≠`)
6038
```julia
6139
tree = AVLTree{Int,Float64}()
6240
63-
# add nodes to the tree
64-
tree[2] = 2.2 # root node
65-
tree[1] = 1.1 # left node
66-
tree[3] = 3.3 # right node
41+
# insert nodes into the tree
42+
BinaryTrees.insert!(tree, 2, 2.2) # root node
43+
BinaryTrees.insert!(tree, 1, 1.1) # left node
44+
BinaryTrees.insert!(tree, 3, 3.3) # right node
6745
6846
# update the value of the node
69-
tree[2] = 2.4
47+
BinaryTrees.insert!(tree, 2, 2.4)
7048
71-
# get the value of the node using its key
72-
tree[2] # 2.4
73-
tree[1] # 1.1
74-
tree[3] # 3.3
49+
# search for nodes using their keys
50+
BinaryTrees.search(tree, 2) # root node
51+
BinaryTrees.search(tree, 1) # left node
52+
BinaryTrees.search(tree, 3) # right node
7553
7654
# delete nodes from the tree
77-
delete!(tree, 1)
78-
delete!(tree, 3)
55+
BinaryTrees.delete!(tree, 1)
56+
BinaryTrees.delete!(tree, 3)
7957
```
8058
"""
81-
mutable struct AVLTree{K,V}
59+
mutable struct AVLTree{K,V} <: BinaryTree
8260
root::Union{AVLNode{K,V},Nothing}
8361
end
8462

8563
AVLTree{K,V}() where {K,V} = AVLTree{K,V}(nothing)
8664
AVLTree() = AVLTree{Any,Any}()
8765

88-
"""
89-
getindex(tree::AVLTree{K}, key::K) where {K}
90-
91-
Get the value stored in the node that has `key`.
92-
"""
93-
function Base.getindex(tree::AVLTree{K}, key::K) where {K}
94-
node = _search(tree, key)
95-
isnothing(node) && throw(KeyError(key))
96-
node.value
97-
end
98-
99-
"""
100-
setindex!(tree::AVLTree{K}, value, key::K) where {K}
66+
search(tree::AVLTree{K}, key::K) where {K} = _search(tree, key)
10167

102-
Add a node to the tree with `key` and `value`.
103-
If a node with `key` already exists, the value
104-
of the node will be updated.
105-
"""
106-
function Base.setindex!(tree::AVLTree{K}, value, key::K) where {K}
68+
function insert!(tree::AVLTree{K}, key::K, value) where {K}
10769
tree.root = _insert!(tree.root, key, value)
10870
tree
10971
end
11072

111-
"""
112-
delete!(tree::AVLTree{K}, key::K) where {K}
113-
114-
Delete the node that has `key` from the tree.
115-
"""
116-
function Base.delete!(tree::AVLTree{K}, key::K) where {K}
73+
function delete!(tree::AVLTree{K}, key::K) where {K}
11774
tree.root = _delete!(tree.root, key)
11875
tree
11976
end
12077

121-
function Base.show(io::IO, ::MIME"text/plain", tree::AVLTree)
122-
if isnothing(tree.root)
123-
print(io, "AVLTree()")
124-
else
125-
println(io, "AVLTree")
126-
str = AbstractTrees.repr_tree(tree.root, context=io)
127-
print(io, rstrip(str)) # remove \n at end
128-
end
129-
end
130-
13178
# -----------------
13279
# HELPER FUNCTIONS
13380
# -----------------

src/binarytree.jl

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# ------------
2+
# BINARY NODE
3+
# ------------
4+
5+
"""
6+
BinaryNode
7+
8+
Binary tree node with key, value and optional left and right children.
9+
"""
10+
abstract type BinaryNode end
11+
12+
"""
13+
BinaryTrees.key(node)
14+
15+
Key of the `node`.
16+
"""
17+
key(node::BinaryNode) = node.key
18+
19+
"""
20+
BinaryTrees.value(node)
21+
22+
Value of the `node`.
23+
"""
24+
value(node::BinaryNode) = node.value
25+
26+
"""
27+
BinaryTrees.left(node)
28+
29+
Left child of the `node`, if it does not exist, `nothing` is returned.
30+
"""
31+
left(node::BinaryNode) = node.left
32+
33+
"""
34+
BinaryTrees.right(node)
35+
36+
Right child of the `node`, if it does not exist, `nothing` is returned.
37+
"""
38+
right(node::BinaryNode) = node.right
39+
40+
# ------------
41+
# BINARY TREE
42+
# ------------
43+
44+
"""
45+
BinaryTree
46+
47+
Binary Tree with a root node.
48+
"""
49+
abstract type BinaryTree end
50+
51+
"""
52+
BinaryTrees.root(tree)
53+
54+
Root node of the `tree`.
55+
"""
56+
root(tree::BinaryTree) = tree.root
57+
58+
"""
59+
BinaryTrees.search(tree, key)
60+
61+
Search the `tree` for the node that has `key`.
62+
If the tree does not have a node with `key`, `nothing` is returned.
63+
"""
64+
function search end
65+
66+
"""
67+
BinaryTrees.insert!(tree, key, value)
68+
69+
Insert a node into the `tree` with `key` and `value`.
70+
If a node with `key` already exists, the value
71+
of the node will be updated.
72+
"""
73+
function insert! end
74+
75+
"""
76+
BinaryTrees.delete!(tree, key)
77+
78+
Delete the node that has `key` from the `tree`.
79+
"""
80+
function delete! end
81+
82+
# -----------
83+
# IO METHODS
84+
# -----------
85+
86+
function Base.show(io::IO, ::MIME"text/plain", tree::BinaryTree)
87+
name = nameof(typeof(tree))
88+
if isnothing(tree.root)
89+
print(io, "$name()")
90+
else
91+
println(io, "$name")
92+
str = AbstractTrees.repr_tree(tree.root, context=io)
93+
print(io, rstrip(str)) # remove \n at end
94+
end
95+
end
96+
97+
# --------------
98+
# ABSTRACTTREES
99+
# --------------
100+
101+
function AbstractTrees.children(node::BinaryNode)
102+
leftnode = left(node)
103+
rightnode = right(node)
104+
if !isnothing(leftnode) && !isnothing(rightnode)
105+
(leftnode, rightnode)
106+
elseif !isnothing(leftnode)
107+
(leftnode,)
108+
elseif !isnothing(rightnode)
109+
(rightnode,)
110+
else
111+
()
112+
end
113+
end
114+
115+
AbstractTrees.NodeType(::Type{<:BinaryNode}) = AbstractTrees.HasNodeType()
116+
AbstractTrees.nodetype(T::Type{<:BinaryNode}) = T
117+
118+
function AbstractTrees.printnode(io::IO, node::BinaryNode)
119+
ioctx = IOContext(io, :compact => true, :limit => true)
120+
show(ioctx, key(node))
121+
print(ioctx, " => ")
122+
show(ioctx, value(node))
123+
end

0 commit comments

Comments
 (0)