3

I have an array of integers representing connectivity of nodes.Consider the following states of the array after each time it's changed:

0|1|2|3|4|5|6|7|8|9 => Root of each node is itself

0|1|2|3|3|5|6|7|8|9 => The root of 4 is 3

0|1|2|8|3|5|6|7|8|9 => The root of 3 is 8, so now 8 is root for 3 as well as 4.

And so on..

Each time two nodes get connected the array changes. I need to draw a tree representing the array state after each connection action. This is what I need to draw:

It's taken from Robert Sedgewick and Kevin Wayne's Algorithms book

It's taken from Robert Sedgewick and Kevin Wayne's Algorithms book.

I've been banging my head against the wall but haven't been able to figure out what strategy I should take to solve this. Should I record the depth of the tree and draw level by level, or should I loop through the array one by one and draw the complete structure of each node with its children? I don't have a clue how to proceed with either way anyway. So I'd appreciate if someone could shed some light on this.

1
  • Try solving using DSU. Dec 15 '17 at 9:57
2

I think your conceptual difficulty is caused by the unstated implication that there is a second set of node 0-9. The array isn't the set of nodes.

Once you realise this the problem becomes simple

The root nodes are those where the array at index of the node Id is equal to the node id.

The children of any node are indicated by the indexes of the array which contain the node id, excluding the index which equals the node id.

ie

array = your input array
nodes = int[] {0,1,2....
roots = nodes.Where(i=> array[i] ==i)

getChildern(int node){
    return nodes.Where(i=> array[i] == node && i != node);
}
1
  • Ah, I had hard times to understand it but finally. Thank you. BTW, that C# Linq is awesome. Dec 20 '17 at 5:08
1

One way to approach it this:

  1. Walk through the array one node at a time from the start
  2. If a node refers to itself, draw it and mark it as drawn
  3. If a node has a different parent, follow the chain to the root (keeping track of each node that you hit along the way
  4. When you get to either the root or a node you've already drawn, draw the chain and mark each one in the chain as drawn.
1

You can try implementing something like DSU. Below is my implementation.

#include<iostream>
#include<vector>

using namespace std;

struct Node{
    int value;
    vector<Node*> childs;
};

/* I am doing a pre-order traversal Here. You can Traverse In any
 way(levelOrder will be best for verification) and verify that the tree constructed iscorrect. 
 */
void traverseOneTree(Node *tree){
    if(tree){
        cout<<tree->value<<" ";
        vector<Node*> child = tree -> childs;
        for(int i=0;i<child.size();i++)
            traverseOneTree(child[i]);
    }
}

void printAllTrees(vector<Node*> &trees){
    for(int i=0;i<trees.size();i++){
            // cout<<"i = "<<i<<trees[i]<<endl;
            traverseOneTree(trees[i]);
            cout<<endl;
    }
}

void join(vector<Node*> &trees,int child,int parent){
    if(trees[child] == NULL || trees[parent] == NULL)
            return; // invalid joining
    else{
        Node *newC = trees[child];
        trees[child] = NULL;
        trees[parent]->childs.push_back(newC);
    }
}

int main(){
    int nodes;
    cin>>nodes;
    vector<Node*> trees(nodes,NULL);
    for(int i=0;i<nodes;i++){
        trees[i] = new Node();
        trees[i]->value = i;
    }

    int joints;
    cin>>joints;
    while(joints--){
        int child,parent;
        cin>>parent>>child;
        join(trees,child,parent);
        printAllTrees(trees);
        cout<<"\n New Join\n";
    }

    return 0;

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.