Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

node_tt.C

Go to the documentation of this file.
00001 //
00002 // node_tt.C : basic tree handling functions
00003 //
00004 
00005 #include "node.h"
00006 
00007 void node::null_pointers()
00008 {
00009     // Clear all pointers (don't touch what they point to)
00010     // -- for use in cleaning up temporary nodes...  Careful!!
00011 
00012     name = NULL;
00013     parent = oldest_daughter = elder_sister = younger_sister = NULL;
00014     log_story = dyn_story = NULL;
00015     hbase = NULL;
00016     sbase = NULL;
00017 }
00018 
00019 int node::n_daughters()
00020 {
00021     if(oldest_daughter == NULL){
00022         return 0;
00023     }else{
00024         int  n = 0;
00025         for ( node * daughter = get_oldest_daughter();
00026               daughter != NULL;
00027               daughter = daughter->get_younger_sister() )
00028             n++;
00029         return n;
00030     }
00031 }
00032 
00033 int node::n_leaves()
00034 {
00035     if(oldest_daughter == NULL){
00036         return 1;
00037     }else{
00038         int  n = 0;
00039         for ( node * daughter = get_oldest_daughter();
00040               daughter != NULL;
00041               daughter = daughter->get_younger_sister() )
00042             n += daughter->n_leaves();
00043         return n;
00044     }
00045 }
00046 
00047 bool node::is_grandparent()
00048     {
00049     bool gp_flag = FALSE;
00050     
00051     for_all_daughters(node, this, n)
00052         if (n->is_parent())
00053             gp_flag = TRUE;
00054 
00055     return gp_flag;
00056     }
00057 
00058 // The following four functions are now inlined and defined in node.h
00059 // (and use the new root member data) -- Steve 9/19/98
00060 
00061 // bool node::is_top_level_node()
00062 // {
00063 //     if (parent == NULL) return FALSE;
00064 //     if (parent->get_parent()) return FALSE;
00065 //     return TRUE;
00066 // }
00067 
00068 // bool node::is_top_level_leaf()
00069 // {
00070 //     if (parent == NULL) return FALSE;
00071 //     if (parent->get_parent()) return FALSE;
00072 //     if (oldest_daughter) return FALSE;
00073 //     return TRUE;
00074 // }
00075 
00076 // bool node::is_low_level_node()
00077 // {
00078 //     if (parent == NULL) return FALSE;
00079 //     if (parent->get_parent() == NULL) return FALSE;
00080 //     return TRUE;
00081 // }
00082 
00083 // bool node::is_low_level_leaf()
00084 // {
00085 //     if (parent == NULL) return FALSE;
00086 //     if (parent->get_parent() == NULL) return FALSE;
00087 //     if (oldest_daughter) return FALSE;
00088 //     return TRUE;
00089 // }
00090 
00091 node* node::get_root()
00092 {
00093     if (root) return root;
00094 
00095     // If root not already set, set it now for future use.
00096 
00097     if (parent == NULL)
00098         root = this;
00099     else
00100         root = get_top_level_node()->get_parent();
00101 
00102     return root;
00103 }
00104 
00105 node* node::get_binary_sister()
00106 {
00107     bool err = false;
00108     node * sister;
00109     if (elder_sister) {
00110         if (elder_sister->get_elder_sister()) {
00111             err = true;
00112         } else {
00113             if (younger_sister) {
00114                 err = true;
00115             } else {
00116                 sister = elder_sister;
00117             }
00118         }
00119     } else {
00120         if (younger_sister) {
00121             if (younger_sister->get_younger_sister()) {
00122                 err = true;
00123             } else {
00124                 sister = younger_sister;
00125             }
00126         } else {
00127             // err_exit("get_binary_sister: no sisters");
00128             warning("get_binary_sister: no sisters!");
00129             PRL(format_label());
00130             PRL(get_parent()->format_label());
00131             if (get_parent() != get_root()) pp2(get_parent(), cerr);
00132             return NULL;
00133         }
00134         
00135     }
00136     if (err) {
00137         warning("get_binary_sister: too many sisters!");
00138         PRL(format_label());
00139         PRL(get_parent()->format_label());
00140         if (get_parent() != get_root()) pp2(get_parent(), cerr);
00141         return NULL;
00142     }
00143     return sister;
00144 }
00145 
00146 real total_mass(node * b)       // should be a member function?
00147 {
00148     real total_mass_nodes = 0;
00149     for_all_daughters(node, b, bi)
00150         total_mass_nodes += bi->get_mass();
00151     return total_mass_nodes;
00152 }
00153 
00154 node * mk_flat_tree(int n, npfp new_node_type, hbpfp a_hbpfp, sbpfp a_sbpfp,
00155                     bool use_stories)
00156 {
00157     node * root, * by, * bo;
00158 
00159     root = (* new_node_type)(a_hbpfp, a_sbpfp, use_stories);
00160     bo = (* new_node_type)(a_hbpfp, a_sbpfp, use_stories);
00161     root->set_oldest_daughter(bo);
00162     bo->set_parent(root);
00163     bo->set_label(1);
00164 
00165     for (int i = 1; i < n; i++) {
00166 
00167         by = (* new_node_type)(a_hbpfp, a_sbpfp, use_stories);
00168         bo->set_younger_sister(by);
00169         by->set_elder_sister(bo);
00170         by->set_parent(root);
00171         by->set_label(i+1);
00172         bo = by;
00173     }
00174 
00175     return root;
00176 }
00177 
00178 char * string_index_of_node(node * n)
00179 {
00180     char * tmp;
00181     tmp = n->get_name();
00182     if (tmp != NULL) {
00183         return tmp;
00184     } else {
00185         static char integer_id[20];
00186         sprintf(integer_id, "%d", n->get_index());
00187         n->set_label(integer_id);
00188         return n->get_name();
00189     }
00190 }
00191 
00192 local char * construct_binary_label(node * ni, node * nj)
00193 {
00194     static char new_name[256];
00195     sprintf(new_name,"(%s,%s)",string_index_of_node(ni),
00196             string_index_of_node(nj));
00197     return new_name;
00198 }
00199 
00200 void label_binary_node(node* n)
00201 {
00202     if (n->is_root()) return;
00203 
00204     for_all_daughters(node, n, nn) label_binary_node(nn);
00205 
00206     if (!n->is_leaf()) {
00207         node* od = n->get_oldest_daughter();
00208         node* yd = od->get_younger_sister();
00209         n->set_label(construct_binary_label(od, yd));
00210     }
00211 }
00212 
00213 // Default label for merger of "a" and "b" is simply "a+b".
00214 // This may lead to unwieldy names in case of multiple mergers.
00215 //
00216 // Alternative is to construct a name that retains the identity
00217 // of the massive component, and merely indicates how many other
00218 // nodes have been destroyed -- really only works well in case
00219 // of dominant motion... (Steve 12/98)
00220 //
00221 // Scheme:      1st merger (b)  -->  a+b (a more massive)
00222 //              2nd merger (c)  -->  a<+2> (a+b more massive)
00223 //                                   c<+2> (c more massive)
00224 //
00225 // Make the alternative the default for now (12/98) -- return later
00226 // to allow options to be passed as arguments.
00227 
00228 local char * construct_merger_label(node * ni, node * nj)
00229 {
00230     static char new_name[1024];
00231     sprintf(new_name, "%s+%s",
00232             string_index_of_node(ni),
00233             string_index_of_node(nj));
00234     return new_name;
00235 }
00236 
00237 local char* string_header(char* string)
00238 {
00239     // Return everything preceding the "<", or everything preceding
00240     // the "+", or else the entire string.
00241 
00242     static char header[1024];
00243     strcpy(header, string);
00244 
00245     char *c = index(header, '<');       // seek "a<+n>"
00246     if (!c) {
00247         c = index(header, '+');         // seek "a+b"
00248         if (!c) return header;
00249     }
00250 
00251     *c = '\0';
00252     return header;
00253 }
00254 
00255 local int string_count(char* string)
00256 {
00257     // Return the integer between the "<" and the ">", or else 1, if
00258     // the string is of the form "a+b", or else 0.
00259 
00260     static char header[1024];
00261     strcpy(header, string);
00262 
00263     char* c1 = index(header, '<');
00264     if (!c1) {
00265         if (index(header, '+')) {
00266 
00267             // return 1;
00268 
00269             // Would be OK to return 1 here if naming were consistent.
00270             // Better to count "+" signs, just in case.
00271 
00272             c1 = header;
00273             int count = 0;
00274             while (*c1 > '\0') {
00275                 if (*c1 == '+') count++;
00276                 c1++;
00277             }
00278 
00279             return count;
00280 
00281         } else
00282             return 0;
00283     }
00284 
00285     char* c2 = index(header, '>');
00286     if (!c2) return 0;                  // (actually an error)
00287     *c2 = '\0';
00288 
00289     return atoi(c1+1);
00290 }
00291 
00292 local char * alt_construct_merger_label(node * ni, node * nj)
00293 {
00294     // Names are of the form:
00295     //
00296     //          ni:     "a" or "a+x" or "a<+n>"
00297     //          nj:     "b" or "b+y" or "b<+m>".
00298     //
00299     // Decode the names and combine them to make the new name.
00300     // Not very efficiently written, but... (Steve, 12/98)
00301 
00302     static char new_name[1024];
00303     int count_i = string_count(string_index_of_node(ni));
00304     int count_j = string_count(string_index_of_node(nj));
00305 
00306     if (count_i+count_j == 0)
00307         return(construct_merger_label(ni, nj));
00308 
00309     sprintf(new_name, "%s<+%d>",
00310             string_header(string_index_of_node(ni)),
00311             count_i + count_j + 1);
00312     return new_name;
00313 }
00314 
00315 void label_merger_node(node* n)
00316 {
00317     node* od = n->get_oldest_daughter();
00318     node* yd = od->get_younger_sister();
00319 
00320     // Added by Steve, 12/98: new label lists more massive
00321     // component first.
00322 
00323     if (od->get_mass() < yd->get_mass()) {
00324         node* tmp = od;
00325         od = yd;
00326         yd = tmp;
00327     }
00328 
00329     n->set_label(alt_construct_merger_label(od, yd));
00330 
00331 //               ^^^^   (note)
00332 
00333 }
00334 
00335 int depth_of_node(node * ni)
00336 {
00337     int depth = 0;
00338     while((ni = ni->get_parent()) != NULL)depth ++;
00339     return depth;
00340 }
00341 
00342 // is_descendent_of: return TRUE if child is among the offspring of parent.
00343 //                   mode = 1 ==> include parent in "offspring" list
00344 //                   mode = 0 ==> exclude parent from consideration
00345 //
00346 int is_descendent_of(node *child, node *parent, int mode)
00347 {
00348     if (mode == 0 && child == parent) return 0;
00349 
00350     while (child != NULL) {
00351         if(child == parent) {
00352             return 1;
00353         } else {
00354             child = child->get_parent();
00355         }
00356     }
00357     return 0;
00358 }
00359 
00360 node * common_ancestor(node * ni, node * nj)
00361 {
00362     int i;
00363     real difference = depth_of_node(ni) - depth_of_node(nj);
00364     if(difference > 0){
00365         for(i = 0; i<difference; i++) ni = ni->get_parent();
00366     }else if (difference < 0){
00367         for(i = 0; i<-difference; i++) nj = nj->get_parent();
00368     }
00369     while(ni != nj){
00370         ni = ni->get_parent();
00371         nj = nj->get_parent();
00372     }
00373     return ni;
00374 }
00375 
00376 node * node_with_index(int i, node * top)       // recursive; default top = NULL
00377 {
00378     if (!top) return NULL;
00379     node * n = top;
00380 
00381     if (n->get_index() == i) return n;
00382 
00383     if (n->get_oldest_daughter() != NULL) {
00384         for_all_daughters(node, n, nn) {
00385             node * tmp = node_with_index(i, nn) ;
00386             if (tmp != NULL) return tmp;
00387         }
00388     }
00389     return NULL;
00390 }
00391 
00392 node * node_with_name(char* s, node * top)      // recursive; default top = NULL
00393 {
00394     if (!top) return NULL;
00395     node * n = top;
00396 
00397     if (n->get_name() != NULL && streq(n->get_name(), s)) return n;
00398 
00399     if (n->get_oldest_daughter() != NULL) {
00400         for_all_daughters(node, n, nn) {
00401             node * tmp = node_with_name(s, nn) ;
00402             if (tmp != NULL) return tmp;
00403         }
00404     }
00405     return NULL;
00406 }
00407 
00408 // detach_node_from_general_tree
00409 // delete node n. Do not check if the parent has more than 2 remaining
00410 // daughters or not.  Do not correct parent mass for removal of node.
00411 
00412 void detach_node_from_general_tree(node & n)
00413 {
00414     if(&n == NULL){
00415         cerr << "Warning: detach_node_from_general_tree, n is null\n";
00416         return;
00417     }
00418 
00419     node *  parent = n.get_parent();
00420     
00421     // check if n is head without parent or sisters
00422     if(parent == NULL){
00423         cerr << "Warning: detach_node_from_general_tree, n has no parent\n";
00424         return;
00425     }
00426 
00427     n.set_parent(NULL);
00428 
00429     node *  elder_sister = n.get_elder_sister();
00430     node *  younger_sister = n.get_younger_sister();
00431 
00432     if (parent->get_oldest_daughter() == &n){
00433         parent->set_oldest_daughter(younger_sister);
00434     }
00435 
00436     if(elder_sister != NULL){
00437         elder_sister->set_younger_sister(younger_sister);
00438     }
00439     if(younger_sister != NULL){
00440         younger_sister->set_elder_sister(elder_sister);
00441     }
00442 }
00443 
00444 
00445 // remove_node_with_one_daughter
00446 // remove the node from the tree
00447 // and replace it by its daughter
00448 // the node should be deleted afterwords
00449 // In principle, virtual destructor should
00450 // work, but I'm not sure what is actually
00451 // done if delete is called in this
00452 // function...
00453 void remove_node_with_one_daughter(node &n)
00454 {
00455     if(n.get_oldest_daughter()->get_younger_sister()!=NULL){
00456         cerr << "remove_node_with_one_daughter: daughters of n is "
00457              << "larger than 1\n";
00458         exit(1);
00459     }
00460     node *  daughter = n.get_oldest_daughter();
00461     if (daughter->get_elder_sister() != NULL ||
00462         daughter->get_younger_sister() != NULL ){
00463         cerr << "remove_node_with_one_daughter: daughter of n has  sisters\n";
00464         exit(1);
00465     }
00466 
00467     node *  parent = n.get_parent();
00468     
00469     // check if n is head without parent or sisters
00470     if(parent == NULL){
00471         cerr << "Warning: remove_node_with_one_daughter, n has no parent\n";
00472         return;
00473     }
00474 
00475     node *  elder_sister = n.get_elder_sister();
00476     node *  younger_sister = n.get_younger_sister();
00477 
00478     if (parent->get_oldest_daughter() == &n) {
00479         parent->set_oldest_daughter(daughter);
00480     }
00481 
00482     if (elder_sister != NULL) {
00483         elder_sister->set_younger_sister(daughter);
00484     }
00485     if (younger_sister != NULL) {
00486         younger_sister->set_elder_sister(daughter);
00487     }
00488 
00489     daughter->set_parent(parent);
00490     daughter->set_younger_sister(younger_sister);
00491     daughter->set_elder_sister(elder_sister);
00492 
00493     // cerr << "remove_node_with_one_daughter: ";
00494     // cerr << "garbage collection not yet implemented\n";
00495 }
00496 
00497 // detach_node_from_binary_tree
00498 // delete node n and repair the tree
00499 
00500 void detach_node_from_binary_tree(node & n)
00501 {
00502     if (&n == NULL) {
00503         cerr << "Warning: detach_node_from_binary_tree, n is null\n";
00504         return;
00505     }
00506 
00507     node *  parent = n.get_parent();
00508 
00509     detach_node_from_general_tree(n);
00510     remove_node_with_one_daughter(*parent);
00511 }
00512     
00513 
00514 // extend_tree
00515 // extend a tree by inserting a new node to a location presently
00516 // occupied by old_n. old_n becomes the only child of the newly
00517 // inserted node. This function returns the address of the
00518 // newly created node
00519 //
00520 
00521 void extend_tree(node& old_n, node& new_n)
00522 {
00523     if (&old_n == NULL) {
00524         cerr << "Warning:extend_tree, old_n is null\n";
00525         return;
00526     }
00527 
00528     // check if old_n is root
00529 
00530     if (old_n.get_parent() == NULL) {
00531         cerr << "extend_tree, old_n is root, cannot insert\n";
00532         exit(1);
00533     }
00534 
00535     // set the pointer of ex-parent of old_n if she was the oldest daughter
00536 
00537     node *  parent = old_n.get_parent();
00538     if (parent->get_oldest_daughter() == (&old_n)) {
00539         // old_n is the oldest daughter of her parent
00540         parent->set_oldest_daughter(&new_n);
00541     }
00542     
00543     // set the pointers of ex-sisters of old_n
00544     node *  elder = old_n.get_elder_sister();
00545     if(elder != NULL){
00546         elder->set_younger_sister(&new_n);
00547     }
00548     node *  younger = old_n.get_younger_sister();
00549     if(younger != NULL){
00550         younger->set_elder_sister(&new_n);
00551     }
00552     
00553     new_n.set_parent(old_n.get_parent());
00554     new_n.set_elder_sister(old_n.get_elder_sister());
00555     new_n.set_younger_sister(old_n.get_younger_sister());
00556     new_n.set_oldest_daughter(&old_n);
00557 
00558     old_n.set_elder_sister(NULL);
00559     old_n.set_younger_sister(NULL);
00560     old_n.set_parent(&new_n);
00561 }
00562 
00563 
00564 
00565 // add_node
00566 // insert n into the tree as the oldest_daughter of the
00567 // parent. The ex-oldest node of the parent becomes the
00568 // younger sister of n.
00569 
00570 void add_node(node &n, node & parent)
00571 {
00572     if (&n == NULL) {
00573         cerr << "Warning:add_node, n is null\n";
00574         return;
00575     }
00576 
00577     if (&parent == NULL) {
00578         cerr << "Warning:add_node, parent is null\n";
00579         return;
00580     }
00581 
00582 // The following part test if n is completely isolated
00583 
00584 #if 0
00585     // check if n is head without parent or sisters
00586 
00587     if (n.get_parent() != NULL) {
00588         cerr << "add_node, n has parent\n";
00589         exit(1);
00590     }
00591     if (n.get_elder_sister() != NULL) {
00592         cerr << "add_node, n has an elder sister\n";
00593         exit(1);
00594     }
00595     if (n.get_younger_sister() != NULL) {
00596         cerr << "add_node, n has an younger sister\n";
00597         exit(1);
00598     }
00599 #endif
00600 
00601     // set the pointers of ex-oldest-daughter of parent
00602 
00603     node *  ex = parent.get_oldest_daughter();
00604     if (ex != NULL) {
00605         ex->set_elder_sister(&n);
00606     }
00607 
00608     parent.set_oldest_daughter(&n);
00609 
00610     n.set_elder_sister(NULL);
00611     n.set_younger_sister(ex);
00612     n.set_parent(&parent);
00613 }
00614     
00615 
00616 // insert_node_into_binary_tree : put in n into the tree by creating
00617 // a new node at the location of old_n and making both old_n and n
00618 // its daughters
00619 
00620 void insert_node_into_binary_tree(node& n, node& old_n, node& new_n)
00621 {
00622     extend_tree(old_n, new_n);
00623     add_node(n, new_n);
00624 }
00625 
00626 // next_node: return the next node to look at when traversing the tree
00627 //            below node b
00628 
00629 node* node::orig_next_node(node* b)
00630 {
00631 
00632     if (oldest_daughter)
00633         return oldest_daughter;
00634     else if (younger_sister)
00635         return younger_sister;
00636     else {
00637 
00638         if (this == b) return NULL;             // In case b is a leaf...
00639         if (parent == b) return NULL;
00640         if (parent == NULL) return NULL;        // Just in case b is atomic...
00641 
00642         node* tmp = parent;
00643         while (tmp->get_younger_sister() == NULL)
00644             if (tmp != b)
00645                 tmp = tmp->get_parent();
00646             else
00647                 return NULL;
00648         
00649         return tmp->get_younger_sister();
00650     }
00651     return NULL;        // To keep some compilers happy... 
00652 }
00653 
00654 // Note from Steve 7/9/98.  This can fail if base is not the root node.
00655 // An attempt to traverse only the tree below a top-level leaf will include
00656 // all nodes to the right of base.
00657 
00658 // This function is used in many places -- changes made here may have
00659 // unexpected consequences elsewhere!  If so, fix is to rename and use
00660 // the new version in in dstar_kira.C and elsewhere
00661 
00662 #define DEBUG 0
00663 
00664 node* node::next_node(node* base)
00665 {
00666     if (DEBUG) {
00667         cerr << "next_node:  node "; print_label(cerr); cerr << endl;
00668         cerr << "            base "; base->print_label(cerr); cerr << endl;
00669     }
00670 
00671     if (oldest_daughter ) {
00672 
00673         if (DEBUG) {
00674             cerr << "return od ";
00675             oldest_daughter->print_label(cerr);
00676             cerr << endl;
00677         }
00678         return oldest_daughter;
00679 
00680 
00681     // NEW!
00682 
00683     } else if (this == base) {          // In case base is a leaf...
00684 
00685         if (DEBUG) cerr << "return NULL 0\n";
00686         return NULL;
00687 
00688 
00689     } else if (younger_sister) {
00690 
00691         if (DEBUG) {
00692             cerr << "return ys ";
00693             younger_sister->print_label(cerr);
00694             cerr << endl;
00695         }
00696         return younger_sister;
00697 
00698     } else {
00699 
00700         // Can't go down or right.  See if we can go up.
00701 
00702         if (this == base) {             // In case base is a leaf...
00703             if (DEBUG) cerr << "return NULL 1\n";
00704             return NULL;
00705         }
00706 
00707         if (parent == NULL) {           // In case b is atomic...
00708             if (DEBUG) cerr << "return NULL 2\n";
00709             return NULL;
00710         }
00711 
00712         node* tmp = parent;
00713         while (tmp->get_younger_sister() == NULL) {
00714             if (tmp == base) {
00715                 if (DEBUG) cerr << "return NULL 3\n";
00716                 return NULL;
00717             } else
00718                 tmp = tmp->get_parent();
00719         }
00720 
00721         // Now tmp is the lowest-level ancestor with a younger sister.
00722 
00723         if (tmp == base) {
00724             if (DEBUG) cerr << "return NULL 4\n";
00725             return NULL;
00726         } else {
00727             if (DEBUG) {
00728                 cerr << "return tys ";
00729                 tmp->get_younger_sister()->print_label(cerr);
00730                 cerr << endl;
00731             }
00732             return tmp->get_younger_sister();
00733         }
00734 
00735     }
00736 
00737     if (DEBUG) cerr << "return NULL 5\n";
00738     return NULL;        // To keep some compilers happy... 
00739 }
00740 
00741 void  err_exit(char * line, node* n)
00742 {
00743     cerr << "error: ";
00744     print_message(line);
00745     if (n) rmtree(n);
00746     exit(1);
00747 }

Generated at Sun Feb 24 09:57:10 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001