/* compress.c */
#include "../Tree.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
create and return an IV object that contains
the map from vertices to fundamental chains.
return value -- # of fundamental chains
created -- 96jun23, cca
-------------------------------------------
*/
IV *
Tree_fundChainMap (
Tree *tree
) {
int nfc, u, v ;
int *map ;
IV *mapIV ;
/*
---------------
check the input
---------------
*/
if ( tree == NULL || tree->n <= 0 ) {
fprintf(stderr, "\n fatal error in Tree_fundChainMap(%p)"
"\n bad input\n", tree) ;
exit(-1) ;
}
mapIV = IV_new() ;
IV_init(mapIV, tree->n, NULL) ;
map = IV_entries(mapIV) ;
for ( v = Tree_postOTfirst(tree), nfc = 0 ;
v != -1 ;
v = Tree_postOTnext(tree, v) ) {
if ( (u = tree->fch[v]) == -1 || tree->sib[u] != -1 ) {
/*
--------------------
v starts a new chain
--------------------
*/
map[v] = nfc++ ;
} else {
/*
-----------------------------------------------
v belongs in the same chain as its only child u
-----------------------------------------------
*/
map[v] = map[u] ;
}
}
return(mapIV) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
compress a tree based on a map from old vertices to new vertices.
the restriction on the map is that the set {u | map[u] = U} must
be connected for all U.
created -- 95nov15, cca
modified -- 96jan04, cca
bug fixed, N computed incorrectly
modified -- 96jun23, cca
in calling sequence, int map[] converted to IV *mapIV
-----------------------------------------------------------------
*/
Tree *
Tree_compress (
Tree *tree,
IV *mapIV
) {
int n, N, u, U, v, V ;
int *head, *link, *map ;
Tree *tree2 ;
/*
---------------
check the input
---------------
*/
if ( tree == NULL
|| (n = tree->n) <= 0
|| mapIV == NULL
|| n != IV_size(mapIV)
|| (map = IV_entries(mapIV)) == NULL ) {
fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)"
"\n bad input\n", tree, mapIV) ;
exit(-1) ;
}
/*
-----------------------
initialize the new tree
-----------------------
*/
N = 1 + IV_max(mapIV) ;
tree2 = Tree_new() ;
Tree_init1(tree2, N) ;
/*
-----------------------------------------------------------
get the head/link construct to map old nodes into new nodes
-----------------------------------------------------------
*/
head = IVinit(N, -1) ;
link = IVinit(n, -1) ;
for ( v = 0 ; v < n ; v++ ) {
if ( (V = map[v]) < 0 || V >= N ) {
fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)"
"\n map[%d] = %d, N = %d\n", tree, map, v, V, N) ;
exit(-1) ;
}
link[v] = head[V] ;
head[V] = v ;
}
/*
---------------------
fill the tree vectors
---------------------
*/
for ( U = 0 ; U < N ; U++ ) {
for ( u = head[U] ; u != -1 ; u = link[u] ) {
if ( (v = tree->par[u]) == -1 ) {
tree2->par[U] = -1 ;
break ;
} else if ( (V = map[v]) != U ) {
tree2->par[U] = V ;
break ;
}
}
}
Tree_setFchSibRoot(tree2) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(head) ;
IVfree(link) ;
return(tree2) ; }
/*--------------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1