/*  util.c  */

#include "../Tree.h"

/*--------------------------------------------------------------------*/
/*
   -------------------------------------------------
   return the first vertex in a post-order traversal
   
   created -- 95nov15, cca
   -------------------------------------------------
*/
int
Tree_postOTfirst (
   Tree   *tree
) {
int   v ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_postOTfirst(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
/*
   ----------------------
   find the leftmost leaf
   ----------------------
*/
if ( (v = tree->root) != -1 ) {
   while ( tree->fch[v] != -1 ) {
      v = tree->fch[v] ;
   }
}
return(v) ; }

/*--------------------------------------------------------------------*/
/*
   ----------------------------------------------------------
   return the vertex that follows v in a post-order traversal
   ----------------------------------------------------------
*/
int
Tree_postOTnext (
   Tree   *tree,
   int    v
) {
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 || v < 0 || v >= tree->n ) {
   fprintf(stderr, "\n fatal error in Tree_postOTnext(%p,%d)"
           "\n bad input\n", tree, v) ;
   exit(-1) ;
}
/*
   ---------------------------------------------------
   find leftmost leaf of sibling (if exists) or parent
   ---------------------------------------------------
*/
if ( tree->sib[v] != -1 ) {
   v = tree->sib[v] ;
   while ( tree->fch[v] != -1 ) {
      v = tree->fch[v] ;
   }
} else {
   v = tree->par[v] ;
}
return(v) ; }
 
/*--------------------------------------------------------------------*/
/*
   ------------------------------------------------
   return the first vertex in a pre-order traversal
   
   created -- 95nov15, cca
   ------------------------------------------------
*/
int
Tree_preOTfirst (
   Tree   *tree
) {
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_preOTfirst(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
return(tree->root) ; }

/*--------------------------------------------------------------------*/
/*
   ---------------------------------------------------------
   return the vertex that follows v in a pre-order traversal
   
   created -- 95nov15, cca
   ---------------------------------------------------------
*/
int
Tree_preOTnext (
   Tree   *tree,
   int    v
) {
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 || v < 0 || v >= tree->n ) {
   fprintf(stderr, "\n fatal error in Tree_preOTnext(%p,%d)"
           "\n bad input\n", tree, v) ;
   exit(-1) ;
}
/*
   -------------------------------------
   find the next vertex in the traversal
   -------------------------------------
*/
if ( tree->fch[v] != -1 ) {
   v = tree->fch[v] ;
} else {
   while ( tree->sib[v] == -1 && tree->par[v] != -1 ) {
      v = tree->par[v] ;
   }
   v = tree->sib[v] ;
}
return(v) ; }
 
/*--------------------------------------------------------------------*/
/*
   ---------------------------------------
   return the number of leaves in the tree

   created -- 95nov15, cca
   ---------------------------------------
*/
int
Tree_nleaves (
   Tree   *tree
) {
int   nleaf, v ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_nleaves(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
 
nleaf = 0 ;
for ( v = 0 ; v < tree->n ; v++ ) {
   if ( tree->fch[v] == -1 ) {
      nleaf++ ;
   }
}
return(nleaf) ; }

/*--------------------------------------------------------------------*/
/*
   -----------------------------------------------
   return the number of roots of the tree (forest)

   created -- 95nov15, cca
   -----------------------------------------------
*/
int
Tree_nroots (
   Tree   *tree
) {
int   nroot, v ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_nroots(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
 
nroot = 0 ;
for ( v = 0 ; v < tree->n ;v++ ) {
   if ( tree->par[v] == -1 ) {
      nroot++ ;
   }
}
return(nroot) ; }
 
/*--------------------------------------------------------------------*/
/*
   -----------------------------------------
   return the number of children of a vertex

   created  -- 95nov15, cca
   modified -- 96jan07, cca
      v checked to be valid
   -----------------------------------------
*/
int
Tree_nchild (
   Tree   *tree,
   int    v
) {
int   nchild, w ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_nchild(%p,%d)"
           "\n bad input\n", tree, v) ;
   exit(-1) ;
}
if ( v < 0 || v >= tree->n ) {
   fprintf(stderr, "\n fatal error in Tree_nchild(%p,%d)"
           "\n v = %d, size = %d\n", tree, v, v, tree->n) ;
   exit(-1) ;
}
nchild = 0 ;
for ( w = tree->fch[v] ; w != -1 ; w = tree->sib[w] ) {
   nchild++ ;
}
return(nchild) ; }

/*--------------------------------------------------------------------*/
/*
   -------------------------------------------
   this method returns an IV object that holds 
   the number of children for the tree nodes.

   created -- 96dec18, cca
   -------------------------------------------
*/
IV *
Tree_nchildIV (
   Tree   *tree
) {
int   n, v, w ;
int   *nchild, *par ;
IV    *nchildIV ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || (n = tree->n) < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_nchildIV(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
nchildIV = IV_new() ;
IV_init(nchildIV, n, NULL) ;
IV_fill(nchildIV, 0) ;
par = tree->par ;
nchild = IV_entries(nchildIV) ;
for ( v = 0 ; v < n ; v++ ) {
   if ( (w = par[v]) != -1 ) {
      nchild[w]++ ;
   }
}

return(nchildIV) ; }

/*--------------------------------------------------------------------*/
/*
   -----------------------------
   return the height of the tree

   created -- 96aug23, cca
   -----------------------------
*/
int
Tree_height (
   Tree   *tree
) {
int   u, v, vheight ;
int   *heights ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_height(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
heights = IVinit(tree->n, 1) ;
for ( v = Tree_postOTfirst(tree) ;
      v != -1 ;
      v = Tree_postOTnext(tree, v) ) {
   if ( (u = tree->fch[v]) == -1 ) {
      vheight = 1 ;
   } else {
      vheight = heights[u] ;
      for ( u = tree->sib[u] ; u != -1 ; u = tree->sib[u] ) {
         if ( vheight < heights[u] ) {
            vheight = heights[u] ;
         }
      }
      vheight++ ;
   }
   heights[v] = vheight ;
}
v = tree->root ;
vheight = heights[v] ;
for ( v = tree->sib[v] ; v != -1 ; v = tree->sib[v] ) {
   if ( vheight < heights[v] ) {
      vheight = heights[v] ;
   }
}
IVfree(heights) ;

return(vheight) ; }

/*--------------------------------------------------------------------*/
/*
   -------------------------------------------------------------
   return the maximum number of children of any node in the tree

   created -- 96sep05, cca
   -------------------------------------------------------------
*/
int
Tree_maxNchild (
   Tree   *tree
) {
int   maxnchild, n, nchild, u, v ;
int   *fch, *sib ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL ) {
   fprintf(stderr, "\n fatal error in Tree_maxNchild(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
n   = tree->n   ;
fch = tree->fch ;
sib = tree->sib ;
maxnchild = 0 ;
for ( v = 0 ; v < n ; v++ ) {
   for ( u = fch[v], nchild = 0 ; u != -1 ; u = sib[u] ) {
      nchild++ ;
   }
   if ( maxnchild < nchild ) {
      maxnchild = nchild ;
   }
}
return(maxnchild) ; }

/*--------------------------------------------------------------------*/
/*
   ---------------------------------------------
   return the number of bytes used by the object
   ---------------------------------------------
*/
int
Tree_sizeOf (
   Tree   *tree
) {
int   nbytes ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL ) {
   fprintf(stderr, "\n fatal error in Tree_sizeOf(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
 
nbytes = sizeof(struct _Tree) + 3*tree->n*sizeof(int) ;
 
return(nbytes) ; }

/*--------------------------------------------------------------------*/


syntax highlighted by Code2HTML, v. 0.9.1