Skip to content

Add support for trees without values #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,10 @@ BinaryTrees.search(tree, 3) # right node
# delete nodes from the tree
BinaryTrees.delete!(tree, 1)
BinaryTrees.delete!(tree, 3)

# tree that only has keys
tree = AVLTree{Int}()
BinaryTrees.insert!(tree, 2) # root node
BinaryTrees.insert!(tree, 1) # left node
BinaryTrees.insert!(tree, 3) # right node
```
15 changes: 11 additions & 4 deletions src/avl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ Base.convert(::Type{AVLNode{K,V}}, node::AVLNode) where {K,V} =
Construct an empty AVL Tree with keys of type `K`
and values of type `V`.

AVLTree()
AVLTree{K}()

Construct an empty AVL Tree that stores keys and values
of any type, alias for `AVLTree{Any,Any}()`.
Construct an empty AVL tree with no values and keys of type `K`.

The keys of AVL Tree must implement sorting operators (`>`, `<`)
and comparison operators (`=`, `≠`)
Expand All @@ -54,14 +53,20 @@ BinaryTrees.search(tree, 3) # right node
# delete nodes from the tree
BinaryTrees.delete!(tree, 1)
BinaryTrees.delete!(tree, 3)

# tree that only has keys
tree = AVLTree{Int}()
BinaryTrees.insert!(tree, 2) # root node
BinaryTrees.insert!(tree, 1) # left node
BinaryTrees.insert!(tree, 3) # right node
```
"""
mutable struct AVLTree{K,V} <: BinaryTree
root::Union{AVLNode{K,V},Nothing}
end

AVLTree{K,V}() where {K,V} = AVLTree{K,V}(nothing)
AVLTree() = AVLTree{Any,Any}()
AVLTree{K}() where {K} = AVLTree{K,Nothing}()

search(tree::AVLTree{K}, key::K) where {K} = _search(tree, key)

Expand All @@ -70,6 +75,8 @@ function insert!(tree::AVLTree{K}, key::K, value) where {K}
tree
end

insert!(tree::AVLTree{K,Nothing}, key::K) where {K} = insert!(tree, key, nothing)

function delete!(tree::AVLTree{K}, key::K) where {K}
tree.root = _delete!(tree.root, key)
tree
Expand Down
19 changes: 14 additions & 5 deletions src/binarytree.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""
BinaryNode

Binary tree node with key, value and optional left and right children.
Binary tree node with key and optional value, left and right children.
"""
abstract type BinaryNode end

Expand All @@ -19,7 +19,7 @@ key(node::BinaryNode) = node.key
"""
BinaryTrees.value(node)

Value of the `node`.
Value of the `node`, if it does not exist, `nothing` is returned.
"""
value(node::BinaryNode) = node.value

Expand Down Expand Up @@ -69,6 +69,10 @@ function search end
Insert a node into the `tree` with `key` and `value`.
If a node with `key` already exists, the value
of the node will be updated.

BinaryTrees.insert!(tree, key)

Insert a node into the `tree` with `key` and no value.
"""
function insert! end

Expand Down Expand Up @@ -117,7 +121,12 @@ AbstractTrees.nodetype(T::Type{<:BinaryNode}) = T

function AbstractTrees.printnode(io::IO, node::BinaryNode)
ioctx = IOContext(io, :compact => true, :limit => true)
show(ioctx, key(node))
print(ioctx, " => ")
show(ioctx, value(node))
val = value(node)
if isnothing(val)
show(ioctx, key(node))
else
show(ioctx, key(node))
print(ioctx, " => ")
show(ioctx, val)
end
end
31 changes: 30 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const BT = BinaryTrees
@test tree |> BT.root |> BT.right |> BT.left |> BT.key == 3

# tree that accepts any types
tree = AVLTree()
tree = AVLTree{Int,Any}()
BT.insert!(tree, 2, 'A')
BT.insert!(tree, 1, 1.1)
BT.insert!(tree, 3, "test")
Expand All @@ -174,6 +174,25 @@ const BT = BinaryTrees
BT.delete!(tree, 2)
@test isnothing(BT.root(tree))

# tree without values
tree = AVLTree{Int}()
BT.insert!(tree, 2)
BT.insert!(tree, 1)
BT.insert!(tree, 3)
@test isnothing(BT.value(BT.search(tree, 2)))
@test isnothing(BT.value(BT.search(tree, 1)))
@test isnothing(BT.value(BT.search(tree, 3)))
BT.delete!(tree, 3)
@test !isnothing(BT.root(tree))
@test !isnothing(BT.left(BT.root(tree)))
@test isnothing(BT.right(BT.root(tree)))
BT.delete!(tree, 1)
@test !isnothing(BT.root(tree))
@test isnothing(BT.left(BT.root(tree)))
@test isnothing(BT.right(BT.root(tree)))
BT.delete!(tree, 2)
@test isnothing(BT.root(tree))

# AbstractTrees interface
tree = AVLTree{Int,Int}()
BT.insert!(tree, 3, 30)
Expand Down Expand Up @@ -210,5 +229,15 @@ const BT = BinaryTrees
│ └─ 1 => 10
└─ 4 => 40
└─ 5 => 50"""

tree = AVLTree{Int}()
BT.insert!(tree, 2)
BT.insert!(tree, 1)
BT.insert!(tree, 3)
@test sprint(show, MIME("text/plain"), tree) == """
AVLTree
2
├─ 1
└─ 3"""
end
end