0

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.

Tim Kochetkov
  • 149
  • 1
  • 11
  • 1
    Here you can see why copy doesn't work as you intend it to work, basically Kotlin is not Java, and things with different names, have different names for a reason. That being said, there are answers here that show you how to make a deep copy. [Kotlin data class copy method not deep copying all members](https://stackoverflow.com/questions/47359496/kotlin-data-class-copy-method-not-deep-copying-all-members) – AlexT Oct 04 '22 at 16:07
  • 2
    That Java version of the clone method wouldn't work either. The new tree is still referencing the same root instance. Unless the Tree constructor manually does a deep clone of the whole tree when it's given a reference. – Tenfour04 Oct 04 '22 at 17:08
  • Yes, I should have added clone method to root. But that leaves with the same problem I am having right now. Tree structure has a lot of nested objects so in order to create a deep copy, I have to go deep down to the deepest TreeNode and then work my way up creating a deep copy of every TreeNode and its children, so that is a recursive problem. – Tim Kochetkov Oct 04 '22 at 17:15
  • How would you create a deep copy of a tree structure? I probably should ask that in a new question. – Tim Kochetkov Oct 04 '22 at 17:15
  • I guess, due to otherwise complexity, I will resort to changing all "visited" flags back to false after traversing, though. – Tim Kochetkov Oct 04 '22 at 17:16

0 Answers0