Edit:
I have found a better way to write the code.
The answer on How to deep copy an N-Ary tree in kotlin is available here How to deep copy an N-Ary tree in kotlin
Written thoroughly so that even a beginner (like me) could understand.
End of edit
I've written a small library for building tree structures in kotlin https://github.com/lifestreamy/TreeBuilder
And as of now I have only one issue with it (you could also see it by running examples.GeneralExample.main(arrayOf()) ):
My methods visualizeTree() and printAllLeafNodes() when called subsequently together do not yield correct results.
In fact, whichever was called first, does its job, the other does not.
This is the relevant code from treeBuilder.Tree:
/**
* Get all nodes in the tree
* The nodes in the list are sorted deep to shallow and right to left
*/
fun getAllNodes(): MutableList<TreeNode<T>> {
val clone = this.clone()
return getAllChildren(clone.root)
}
/**
* Get all children nodes below the passed node
* after passing all nodes' parameter VISITED is set to true, so we should use this operation on a treeNode.clone() !
*/
fun getAllChildren(node: TreeNode<T>): MutableList<TreeNode<T>> {
val childrenList = mutableListOf<TreeNode<T>>()
while (node.hasChildren() && !node.visited) {
node.childrenList.forEach {
childrenList.let { list1 -> getAllChildren(it).let(list1::addAll) }
}
node.visited = true
}
childrenList.add(node)
return childrenList
}
/**
* Use to make an independent instance of this treeBuilder
*/
fun clone() = this.copy()
/**
* Print all nodes in a node list, each node shifted by 20 * its depth
*/
fun printNodesWithDepth(nodeList: MutableList<TreeNode<T>>) {
nodeList.forEach {
println(" ".repeat(20 * it.depth) + "(${it.depth}) ${it.name}")
}
}
/**
* Prints out all leaves, each shifted by 20 * its depth
*/
fun printAllLeafNodes(){
val allLeafNodes = this.getAllLeaves()
println("All leaf nodes (amount = ${allLeafNodes.size}) are:")
printNodesWithDepth(allLeafNodes)
}
/**
* Get visualization of the whole tree
* How to read visualization:
* All nodes with (x) > (x) of the node left to it
* and that are above that node are its children
*/
fun visualizeTree() {
val allTreeNodes = this.getAllNodes()
println("All nodes (amount = ${allTreeNodes.size}) are:")
printNodesWithDepth(allTreeNodes)
}
At first this used to happen because when I called getAllChildren(), the tree was traversed and every node parameter "visited" was set to true
So when I traversed it again, the first node was already visited and no nodes were returned.
So I added a clone() method which essentially clones this tree with copy(), and it should return new Tree, like in Java.
But as I understand, it does not.
So the result of calling visualizeTree() and printAllLeafNodes() subsequently on clones is the same as if I called them on a single instance of a Tree.
I have no idea, why this copy() does not get me a new instance. In java, clone() would have been written something like this:
public Tree<T> clone(Tree<T> tree) {
return new Tree(tree.root);
}
Could you suggest any solution to this?
For now, if copy() does not work, the only option for me would be to traverse the tree again and set all "visited" flags back to false, but that does not seem optimal.
Thanks.