Skip to content
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
49 changes: 47 additions & 2 deletions src/LeftChildRightSiblingTrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export Node,
isleaf,
islastsibling,
lastsibling,
prunebranch!
prunebranch!,
copy_subtree

mutable struct Node{T}
data::T
Expand Down Expand Up @@ -100,6 +101,50 @@ function addchild(parent::Node{T}, data) where T
newc
end

"""
child = addchild(parent::Node{T}, data::Node{T}) where {T}

Add a node `data` as the last child of `parent`. Requires that `data` is a root node.
"""
function addchild(parent::Node{T}, data::Node{T}) where T
if !isroot(data)
error("Child node must be a root node")
end
prevc = parent.child
if prevc == parent
parent.child = data
else
prevc = lastsibling(prevc)
prevc.sibling = data
end
data.parent = parent
data
end

"""
new_root = copy_subtree(root::Node{T}) where {T}

Get a shallow copy of the subtree rooted at `root`. Note that this does not copy the
data, and only copies the tree structure.
"""
function copy_subtree(root::Node{T}) where {T}
new_root = Node{T}(root.data)
if !isleaf(root)
last_child = new_root
for child in root
new_child = copy_subtree(child)
if last_child === new_root
new_root.child = new_child
else
last_child.sibling = new_child
end
new_child.parent = new_root
last_child = new_child
end
end
return new_root
end

"""
isroot(node)

Expand Down Expand Up @@ -239,7 +284,7 @@ function Base.:(==)(a::Node, b::Node)
reta, retb = iterate(a), iterate(b)
while true
reta === retb === nothing && return true
(reta === nothing) || (retb === nothing) && return false
((reta === nothing) || (retb === nothing)) && return false
childa, statea = reta
childb, stateb = retb
childa == childb || return false
Expand Down
32 changes: 32 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,38 @@ end
c = collect(tree1)
addchild(last(c), "Kid")
@test tree1 != tree2

root = Node(1)
otherroot = Node(2)
addchild(otherroot, 3)
addchild(otherroot, 4)
newc = addchild(root, otherroot)
@test newc === otherroot
@test !isleaf(root)
@test depth(root) == 3
@test map(x -> x.data, collect(PreOrderDFS(root))) == [1, 2, 3, 4]
tmp = Node(0)
@test_throws ErrorException addchild(tmp, otherroot)
thirdroot = Node(5)
addchild(thirdroot, 6)
addchild(thirdroot, 7)
newc = addchild(root, thirdroot)
@test newc === thirdroot
@test map(x -> x.data, collect(PreOrderDFS(root))) == [1, 2, 3, 4, 5, 6, 7]

@test !islastsibling(otherroot)
copied_root = copy_subtree(otherroot)
@test AbstractTrees.isroot(copied_root)
@test islastsibling(copied_root)
for (oldchild, newchild) in zip(otherroot, copied_root)
@test oldchild.parent === otherroot
@test newchild.parent === copied_root
end

leaf = Node(2)
copied_leaf = copy_subtree(leaf)
@test isleaf(leaf)
@test isleaf(copied_leaf)
end

@testset "AbstractTrees" begin
Expand Down
Loading