简体   繁体   中英

Creation of a n-ary tree through level based tree traversal of another

So i am traversing level-wise an n-ary tree having nodes with attributes id and name, i want to alter the name of each node and create another similar n-ary tree with the altered nodes (the root node having A as id )

    Queue<Node> queue = new LinkedList<>();
    // node being the root node of the already created n-ary tree
    queue.add(node);
    Node rootOut = new Node(node.id,node.name);
    Node copiedNode = null;
    Node resNode = null;
    // iterate while queue not empty
    while(!queue.isEmpty()){

        // dequeue
        Node next = queue.remove();
    
 
        
        copiedNode = new Node(next.id,next.name);
        for (Node child : next.children) {
           

            Node copiedChildNode = new Node(child.id,child.name);
            copiedNode.children.add(copiedChildNode);
            if (next.id == "A") rootOut = copiedNode;
            queue.add(child);
        }
    }
    return rootOut ;

But this doesn't return the root node of a correct new tree. In fact this returns just the root node and its immediate children but no further depth. Could anybody help to do that properly

Your attempt is not tracking the copies you're making, so you're not building a tree, just a bunch of single-node copies and their children:

    queue.add(node);
    Node copiedNode = null;

    while(!queue.isEmpty()){
        Node next = queue.remove();

        // A new copy (not being referenced by anything)
        copiedNode = new Node(next.id,next.name);
        for (Node child : next.children) {
           

            // A new copy (referenced by only the aforementioned copy
            Node copiedChildNode = new Node(child.id,child.name);
            copiedNode.children.add(copiedChildNode);

            // If the original was "A", store a reference to the copy.
            if (next.id == "A") rootOut = copiedNode;

            // The original is queued, not the copy
            queue.add(child);
        }
    }
 
    // Return only the shallow copy
    return rootOut ;

You need to build a structure in the copy, tracking the references:

    Queue<Node> queue = new LinkedList<>();
    queue.add(node);
    Node rootOut = new Node(node.id,node.name);

    // For tracking copies
    Map<String, Node> copiedNodesById = new HashMap<>();
    copiedNodesById.put(rootOut.id, rootOut);

    while(!queue.isEmpty()){

        Node currentOriginal = queue.remove();
        // Get an existing copy rather than making a new one.
        Node currentCopy = copiedNodesById.get(currentOriginal.id);
        
        for (Node childOriginal : currentOriginal.children) {

            Node copiedChildNode = new Node(childOriginal.id,childOriginal.name);
            currentCopy.children.add(copiedChildNode);

            // Track the copy that was just made.
            copiedNodesById.put(copiedChildNode.id, copiedChildNode);
            
            if (next.id == "A") rootOut = currentCopy;
            queue.add(childOriginal);
        }
    }
    return rootOut ;

I took the liberty of renaming some variables to make it clearer what is original vs a copy.

The copied nodes could have also been tracked in another queue as well. Or the queue could track (original, copy) tuples instead.

As for restructuring the copy based on the location of "A", I'll leave that to you since it's unclear to me how that is supposed to function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM