简体   繁体   中英

Print ancestors of all nodes in a Binary Tree. Can we do it in less than O(n^2) time complexity?

This is the standard algorithm for printing ancestors of a particular Node in a Binary Tree and it takes O(n) time complexity.

bool print(Node *node,int target){
    if(node==NULL)
       return false;
    if(node->target==target)
       return true;
    if(print(node->left)||print(node->right)){
       cout << node->data;
       return true;
    }
return false;
}

The question is if we need to print all ancestors of all node's and also store ancestors in an array for each node. what is the time complexity? Can we do it better than O(n^2) ie without looping through each node and find ancestors.If possible how?

If you want an array corresponding to each node in the tree, then you cannot do better than O(N 2 ) worst case, because the total size of all arrays is worst case O(N 2 ) (in the case that every node in the tree has at most one child). If you expect the trees to be somewhat balanced, this reduces to O(N log N).

You can achieve O(N) construction by sharing data, using a linked list instead of an array for each node. In effect, that's equivalent to computing a parent link for each node, because the linked list is simply a traversal of parent links. But you cannot avoid the cost of printing, because you will print average O(N log N) / worst case O(N 2 ) items when you print out all the ancestor chains.

The parent link construction algorithm is basically the same as the algorithm you present: recursively walk the tree setting the parent links of the children to the current node. To print the ancestor chains for each node, you can use the parent links while you walk the tree.

It can be done in O(n*h) , where h is the tree's height, by implementing a DFS , that keeps track of currently open nodes.

A simple c++ like pseudo code can be something like:

void PrintAll(const Node& node) {
  open = std::unordered_set<Node>;  // empty hash set
  PrintAll(node, &open);
}
void PrintAll(const Node& node, std::unordered_set* open) {
  if (node == null) 
     return;
  for (const Node& ancestor: open)
     cout << ancestor<< "," << node;
  open->add(node);
  PrintAll(node.left, open);
  PrintAll(node.right, open);
  open->remove(node);
}

Caveat: In here, we do not print (node, node) (each node is also an ancestor of itself). If we want to do it, it can be fixed easily by adding the addition of node to open before the printing loop.
Also, you can make the unordered_set store only the data, rather than the entire node.

The following code will do the job :

Language Used : Java

//  Algorithm for printing the ancestors of a Node.
static boolean findAncestors(Node root, Node a)
{
    if(root==null)
    {
        return false;
    }
    else if(root==a)
    {
        System.out.print("Printing ancestors of node " + a.data + " : " + a.data);
        return true;
    }
    else
    {
        boolean var=false;
        var=findAncestors(root.left, a);
        if(var)
        {
            System.out.print(", " + root.data);
            return true;
        }

        var=findAncestors(root.right, a);
        if(var)
        {
            System.out.print(", " + root.data);
            return true;
        }

    }
    return false;
}

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