/*  justify.c  */

#include "../Tree.h"

/*--------------------------------------------------------------------*/
/*
   ------------------------------------------------------------
   left-justify a tree by subtree size
   children are linked in ascending order of their subtree size

   created -- 96jun23, cca
   ------------------------------------------------------------
*/
void
Tree_leftJustify (
   Tree   *tree
) {
IV   *tmetricIV, *vmetricIV ;
/*
   ---------------
   check the input
   ---------------
*/
if ( tree == NULL || tree->n < 1 ) {
   fprintf(stderr, "\n fatal error in Tree_leftJustify(%p)"
           "\n bad input\n", tree) ;
   exit(-1) ;
}
/*
   ------------------------------------------------------------------
   set the subtree size metric, left justify and free working storage
   ------------------------------------------------------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, tree->n, NULL) ;
IV_fill(vmetricIV, 1) ;
tmetricIV = Tree_setSubtreeImetric(tree, vmetricIV) ;
Tree_leftJustifyI(tree, tmetricIV) ;
IV_free(vmetricIV) ;
IV_free(tmetricIV) ;
 
return ; }

/*--------------------------------------------------------------------*/
/*
   ------------------------------------------------------
   left-justify a tree by a metric
   children are linked in ascending order of their metric

   created -- 96jun23, cca
   ------------------------------------------------------
*/
void
Tree_leftJustifyI (
   Tree   *tree,
   IV     *metricIV
) {
int   i, j, k, n, nexti, prev ;
int   *fch, *metric, *par, *sib ;
/*
   ---------------
   check the input
   ---------------
*/
if (  tree == NULL 
   || (n = tree->n) <= 0 
   || metricIV == NULL 
   || n != IV_size(metricIV)
   || (metric = IV_entries(metricIV)) == NULL ) {
   fprintf(stderr, "\n fatal error in Tree_leftJustifyI(%p,%p)"
           "\n bad input\n", tree, metricIV) ;
   exit(-1) ;
}
par = tree->par ;
fch = tree->fch ;
sib = tree->sib ;
/*
   ----------------------------------------------------
   sort all children in decreasing order of metric size
   ----------------------------------------------------
*/
for ( k = 0 ; k < n ; k++ ) {
   for ( i = fch[k], fch[k] = -1 ; i != -1 ; i = nexti ) {
      nexti = sib[i] ;
      for ( j = fch[k], prev = -1 ; j != -1 ; j = sib[j] ) {
         if ( metric[j] < metric[i] ) {
            break ;
         }
         prev = j ;
      }
      if ( prev == -1 ) {
         fch[k] = i ;
      } else {
         sib[prev] = i ;
      }
      sib[i] = j ;
   }
}
/*
   ---------------------------------------------
   sort roots in decreasing order of metric size
   ---------------------------------------------
*/
for ( i = tree->root, tree->root = -1, prev = -1 ; 
      i != -1 ; 
      i = nexti ) {
   nexti = sib[i] ;
   for ( j = tree->root, prev = -1 ; j != -1 ; j = sib[j] ) {
       if ( metric[j] < metric[i] ) {
          break ;
       }
      prev = j ;
   }
   if ( prev == -1 ) {
      tree->root = i ;
   } else {
      sib[prev] = i ;
   }
   sib[i] = j ;
}
 
return ; }

/*--------------------------------------------------------------------*/
/*
   ------------------------------------------------------
   left-justify a tree by a metric
   children are linked in ascending order of their metric

   created -- 96jun23, cca
   ------------------------------------------------------
*/
void
Tree_leftJustifyD (
   Tree   *tree,
   DV     *metricDV
) {
int      i, j, k, n, nexti, prev ;
int      *fch, *par, *sib ;
double   *metric ;
/*
   ---------------
   check the input
   ---------------
*/
if (  tree == NULL 
   || (n = tree->n) <= 0 
   || metricDV == NULL 
   || n != DV_size(metricDV)
   || (metric = DV_entries(metricDV)) == NULL ) {
   fprintf(stderr, "\n fatal error in Tree_leftJustifyD(%p,%p)"
           "\n bad input\n", tree, metricDV) ;
   exit(-1) ;
}
par = tree->par ;
fch = tree->fch ;
sib = tree->sib ;
/*
   ----------------------------------------------------
   sort all children in decreasing order of metric size
   ----------------------------------------------------
*/
for ( k = 0 ; k < n ; k++ ) {
   for ( i = fch[k], fch[k] = -1 ; i != -1 ; i = nexti ) {
      nexti = sib[i] ;
      for ( j = fch[k], prev = -1 ; j != -1 ; j = sib[j] ) {
         if ( metric[j] < metric[i] ) {
            break ;
         }
         prev = j ;
      }
      if ( prev == -1 ) {
         fch[k] = i ;
      } else {
         sib[prev] = i ;
      }
      sib[i] = j ;
   }
}
/*
   ---------------------------------------------
   sort roots in decreasing order of metric size
   ---------------------------------------------
*/
for ( i = tree->root, tree->root = -1, prev = -1 ; 
      i != -1 ; 
      i = nexti ) {
   nexti = sib[i] ;
   for ( j = tree->root, prev = -1 ; j != -1 ; j = sib[j] ) {
       if ( metric[j] < metric[i] ) {
          break ;
       }
      prev = j ;
   }
   if ( prev == -1 ) {
      tree->root = i ;
   } else {
      sib[prev] = i ;
   }
   sib[i] = j ;
}
 
return ; }

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


syntax highlighted by Code2HTML, v. 0.9.1