Search code examples
c++calgorithmdata-structuresadvanced-search

All parents of a node in BST?


While printing Binary Search Tree(BST) using recursive function (pre-order). I need to print all the parents(path form root) of current node.
An auxiliary data structure can(e.g. path in my code) be use but I don't want to keep node->path to store path.

      4                           
     / \  
    /   \  
   2     6
  / \   / \
 1   3  5  7  

Suppose I am printing nodes in rows using pre-order traverse:

NODE    PATH  
4       4  
2       4,2  
1       4,2,1
3       4,2,3       
6       4,6
5       4,6,5
7       4,6,7  

I did as follows: Working fine!
Path end with 0 (Zero) value in this code. And there is no node value is 0 in BST.

void printpath(int* mypath){
   while(*mypath)  
      printf("%d ", *mypath++);  
}

void preorder(struct tree *p, int* path){
    int *mypath = calloc(sizeof(path)/sizeof(int) + 1 , sizeof(int*));
    int* myp=mypath;

    if(p!=NULL){  
       while( *myp++ = *path++ );  
       --myp;
       *myp=p->data;
       *(myp+1)=0;

        printf("%d PATH ",p->data);
        printpath(mypath);
        printf("\n");
        preorder(p->left, mypath);
        preorder(p->right, mypath);
    }
    free(mypath);
}

But I don't want to keep path array as there is lots of nodes in BST. Can some one suggest me other data-structure/ or method ? A suggestion would be enough but should be efficient.


Solution

  • Here's an old trick, which still works: keep the back pointers in the call stack.

        struct stacked_list{
          struct stacked_list* prev;
          struct tree* tree; 
        };
    
       void printpath_helper(int data, struct stacked_list* path) {
          if (!path->prev)
            printf("%d PATH ", data);
          else
            printpath_helper(data, path->prev);
          printf("%d ", path->tree->data);
        }
    
        void printpath(struct stacked_list* path) {
          printpath_helper(path->tree->data, path);
          putchar('\n');
        }
    
        void preorder_helper(struct stacked_list* path) {
          if (path->tree) {
            printpath(path);
            struct stacked_list child = {path, path->tree->left};
            preorder_helper(&child);
            child.tree = path->tree->right;
            preorder_helper(&child);
          }
        }
    
        void preorder(struct tree* tree) {
          struct stacked_list root = {NULL, tree};
          preorder_helper(&root);
        }
    

    Each recursion of preorder_helper creates an argument struct and passes its address to the next recursion, effectively creating a linked list of arguments which printpath_helper can walk up to actually print the path. Since you want to print the path from top to bottom, printpath_helper needs to also reverse the linked list, so you end up doubling the recursion depth of the function; if you could get away with printing bottom to top, printpath_helper could be a simple loop (or tail recursion).