Skip to content

Commit 9d0a0bc

Browse files
committed
Add utility functions to traverse trees to find minimum, maximum nodes within the tree and within subtrees, and an abovebelow function that returns the nodes immediately above and below a given BinaryNode
1 parent 5e89b74 commit 9d0a0bc

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

src/binarytree.jl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,67 @@ function _printkeyvalue(io::IO, node::BinaryNode)
143143
show(ioctx, val)
144144
end
145145
end
146+
147+
# -----------
148+
# UTILITIES
149+
# -----------
150+
151+
minnode(tree::BinaryTree) = minnode(root(tree))
152+
153+
function minnode(node::BinaryNode)
154+
leftnode = left(node)
155+
isnothing(leftnode) ? node : minnode(leftnode)
156+
end
157+
158+
minnode(node::Nothing) = nothing
159+
160+
maxnode(tree::BinaryTree) = maxnode(root(tree))
161+
162+
function maxnode(node::BinaryNode)
163+
rightnode = right(node)
164+
isnothing(rightnode) ? node : maxnode(rightnode)
165+
end
166+
167+
maxnode(node::Nothing) = nothing
168+
169+
function abovebelow(tree::BinaryNode, x::BinaryNode)
170+
above, below = nothing, nothing
171+
current = tree
172+
# Traverse from the root to the target node, updating candidates.
173+
while !isnothing(current) && key(current) != key(x)
174+
if key(x) < key(current)
175+
# current is a potential above (successor)
176+
above = current
177+
current = left(current)
178+
else # x.key > current.key
179+
# current is a potential below (predecessor)
180+
below = current
181+
current = right(current)
182+
end
183+
end
184+
185+
# If the node wasn't found, return the best candidate values
186+
if isnothing(current)
187+
return (above, below)
188+
end
189+
190+
# Found the node with key equal to x.key.
191+
# Now, if there is a left subtree, the true below (predecessor) is the maximum in that subtree.
192+
if !isnothing(left(current))
193+
below = maxnode(left(current))
194+
end
195+
# Similarly, if there is a right subtree, the true above (successor) is the minimum in that subtree.
196+
if !isnothing(right(current))
197+
above = minnode(right(current))
198+
end
199+
200+
(above, below)
201+
end
202+
203+
function abovebelow(tree::BinaryTree, x::BinaryNode)
204+
abovebelow(root(tree), x)
205+
end
206+
207+
function abovebelow(tree, x::Nothing)
208+
(nothing, nothing)
209+
end

test/runtests.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const BT = BinaryTrees
9393
BT.insert!(tree, 2, 20)
9494
BT.insert!(tree, 1, 10)
9595
BT.insert!(tree, 3, 30)
96-
# deleting a key that does not exist
96+
# deleting a key that does not exist
9797
# does not change the tree
9898
BT.delete!(tree, 4)
9999
@test tree === tree
@@ -219,11 +219,32 @@ const BT = BinaryTrees
219219
@test BT.value(BT.search(tree, (0, 0, 1))) == 1
220220
@test BT.value(BT.search(tree, (1, 0, 0))) == 3
221221

222+
# traversal algorithms
223+
tree = AVLTree{Int,Float64}()
224+
BT.insert!(tree, 0, 5)
225+
BT.insert!(tree, 1, 6)
226+
BT.insert!(tree, 2, 8)
227+
BT.insert!(tree, 3, 10)
228+
BT.insert!(tree, 4, 20)
229+
BT.insert!(tree, 5, 30)
230+
BT.insert!(tree, 6, 40)
231+
@test BT.key(BT.minnode(tree)) == 0
232+
@test BT.key(BT.maxnode(tree)) == 6
233+
@test BT.abovebelow(tree, BT.AVLNode(0, 5))[2] == nothing
234+
@test BT.key.(BT.abovebelow(tree, BT.AVLNode(2, 10))) == (3, 1)
235+
@test BT.key.(BT.abovebelow(BT.root(tree), BT.AVLNode(2, 10))) == (3, 1)
236+
@test BT.key.(BT.abovebelow(tree, BT.AVLNode(5, 30))) == (6, 4)
237+
@test BT.abovebelow(tree, nothing) == (nothing, nothing)
238+
@test BT.abovebelow(BT.root(tree), nothing) == (nothing, nothing)
239+
222240
# type stability
223241
tree = AVLTree{Int,Int}()
224242
@inferred BT.insert!(tree, 2, 20)
225243
@inferred BT.insert!(tree, 1, 10)
226244
@inferred BT.insert!(tree, 3, 30)
245+
@inferred BT.minnode(tree)
246+
@inferred BT.maxnode(tree)
247+
@inferred BT.abovebelow(tree, BT.AVLNode(2, 20))
227248
@inferred Nothing BT.search(tree, 2)
228249
@inferred Nothing BT.search(tree, 1)
229250
@inferred Nothing BT.search(tree, 3)

0 commit comments

Comments
 (0)