Skip to content
60 changes: 60 additions & 0 deletions src/binarytree.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,63 @@ function _printkeyvalue(io::IO, node::BinaryNode)
show(ioctx, val)
end
end

# -----------
# UTILITIES
# -----------

minnode(tree::BinaryTree) = minnode(root(tree))

function minnode(node::BinaryNode)
leftnode = left(node)
isnothing(leftnode) ? node : minnode(leftnode)
end

minnode(node::Nothing) = nothing

maxnode(tree::BinaryTree) = maxnode(root(tree))

function maxnode(node::BinaryNode)
rightnode = right(node)
isnothing(rightnode) ? node : maxnode(rightnode)
end

maxnode(node::Nothing) = nothing

function prevnext(tree::BinaryTree, k)
prev, next = nothing, nothing
current = root(tree)
# Traverse from the root to the target node, updating candidates.
while !isnothing(current) && key(current) != k
if k < key(current)
# current is a potential next (successor)
next = current
current = left(current)
else # k.key > current.key
# current is a potential previous (predecessor)
prev = current
current = right(current)
end
end

# If the node wasn't found, return the best candidate values
if isnothing(current)
return (prev, next)
end

# Found the node with key equal to x.key.
# Now, if there is a left subtree, the true previous (predecessor) is the maximum in that subtree.
if !isnothing(left(current))
prev = maxnode(left(current))
end
# Similarly, if there is a right subtree, the true next (successor) is the minimum in that subtree.
if !isnothing(right(current))
next = minnode(right(current))
end

(prev, next)
end

function prevnext(tree::BinaryTree, k::Nothing)
(nothing, nothing)
end
26 changes: 25 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const BT = BinaryTrees
BT.insert!(tree, 2, 20)
BT.insert!(tree, 1, 10)
BT.insert!(tree, 3, 30)
# deleting a key that does not exist
# deleting a key that does not exist
# does not change the tree
BT.delete!(tree, 4)
@test tree === tree
Expand Down Expand Up @@ -219,11 +219,29 @@ const BT = BinaryTrees
@test BT.value(BT.search(tree, (0, 0, 1))) == 1
@test BT.value(BT.search(tree, (1, 0, 0))) == 3

# traversal algorithms
tree = AVLTree{Int,Float64}()
BT.insert!(tree, 0, 5)
BT.insert!(tree, 1, 6)
BT.insert!(tree, 2, 8)
BT.insert!(tree, 3, 10)
BT.insert!(tree, 4, 20)
BT.insert!(tree, 5, 30)
BT.insert!(tree, 6, 40)
@test BT.key(BT.minnode(tree)) == 0
@test BT.key(BT.maxnode(tree)) == 6
@test BT.prevnext(tree, 0)[1] == nothing
@test BT.key.(BT.prevnext(tree, 2)) == (1, 3)
@test BT.key.(BT.prevnext(tree, 5)) == (4, 6)
@test BT.prevnext(tree, nothing) == (nothing, nothing)

# type stability
tree = AVLTree{Int,Int}()
@inferred BT.insert!(tree, 2, 20)
@inferred BT.insert!(tree, 1, 10)
@inferred BT.insert!(tree, 3, 30)
@inferred Nothing BT.minnode(tree)
@inferred Nothing BT.maxnode(tree)
@inferred Nothing BT.search(tree, 2)
@inferred Nothing BT.search(tree, 1)
@inferred Nothing BT.search(tree, 3)
Expand All @@ -234,6 +252,8 @@ const BT = BinaryTrees
@inferred BT.insert!(tree, 2)
@inferred BT.insert!(tree, 1)
@inferred BT.insert!(tree, 3)
@inferred Nothing BT.minnode(tree)
@inferred Nothing BT.maxnode(tree)
@inferred Nothing BT.search(tree, 2)
@inferred Nothing BT.search(tree, 1)
@inferred Nothing BT.search(tree, 3)
Expand All @@ -244,6 +264,8 @@ const BT = BinaryTrees
@inferred BT.insert!(tree, "key2", 2)
@inferred BT.insert!(tree, "key1", 1)
@inferred BT.insert!(tree, "key3", 3)
@inferred Nothing BT.minnode(tree)
@inferred Nothing BT.maxnode(tree)
@inferred Nothing BT.search(tree, "key2")
@inferred Nothing BT.search(tree, "key1")
@inferred Nothing BT.search(tree, "key3")
Expand All @@ -254,6 +276,8 @@ const BT = BinaryTrees
@inferred BT.insert!(tree, (0, 1, 0), 2)
@inferred BT.insert!(tree, (0, 0, 1), 1)
@inferred BT.insert!(tree, (1, 0, 0), 3)
@inferred Nothing BT.minnode(tree)
@inferred Nothing BT.maxnode(tree)
@inferred Nothing BT.search(tree, (0, 1, 0))
@inferred Nothing BT.search(tree, (0, 0, 1))
@inferred Nothing BT.search(tree, (1, 0, 0))
Expand Down
Loading