home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / basic / _bb_tree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  18.3 KB  |  691 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _bb_tree.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //--------------------------------------------------------------------
  17. //  
  18. //  BB[alpha] Trees
  19. //
  20. //  Michael Wenzel   (1989)
  21. //
  22. // Implementation as described in
  23. // Kurt Mehlhorn: Data Structures and Algorithms 1, section III.5.1
  24. //
  25. // -------------------------------------------------------------------
  26. // Aenderungen:
  27. //   - keine virtuellen Funktionen  (M. Wenzel, Nov. 1989)
  28. //   - nicht rekursiv               (M. Wenzel, Nov. 1989)
  29. //   - virtuelle compare-Funktion   (M. Wenzel, Nov. 1989)
  30. //--------------------------------------------------------------------
  31.  
  32.  
  33.  
  34. #undef TEST
  35. #undef DUMP
  36.  
  37. #include <LEDA/bb_tree.h>
  38.  
  39. #ifdef TEST
  40. #define DPRINT(x) cout << string x
  41. #else
  42. #define DPRINT(x)   
  43. #endif
  44.  
  45. #ifdef DUMP
  46. #define DDUMP(x) cout << string x
  47. #else
  48. #define DDUMP(x)   
  49. #endif
  50.  
  51.  
  52.  
  53. enum children { left = 0 , right = 1 };
  54.  
  55. enum leaf_or_node { Leaf = 0 , Node = 1 } ;
  56.  
  57.  
  58. // -------------------------------------------------------------
  59. // member functions
  60. // -------------------------------------------------------------
  61.  
  62.  
  63.   bb_tree::bb_tree(float a)   : st(BSTACKSIZE)
  64.   { 
  65.     root = first = iterator = 0;
  66.     anzahl=0;
  67.     if ((a<=0.25) || (a>1-SQRT1_2))
  68.       error_handler(3,"alpha not in range");
  69.     alpha=a;
  70.     d = 1/(2-alpha) ;
  71.   }
  72.  
  73.   bb_tree::bb_tree(bb_tree& w)  : st(BSTACKSIZE)
  74.   { 
  75.     bb_item p;
  76.     bb_item l=0;
  77.     anzahl=w.anzahl;
  78.     alpha=w.alpha;
  79.     d=w.d;
  80.     iterator=0;
  81.     if (w.root)
  82.     { if (!w.root->blatt())
  83.       { p=new bb_node(w.root);
  84.         first=copytree(p,w.root,l); 
  85.         first->sohn[left]=l;
  86.         l->sohn[right]=first; }
  87.       else
  88.       { p=new bb_node(w.root);
  89.         first=p; }
  90.       root= p;                      }
  91.     else root = 0;
  92.   }
  93.  
  94. // -------------------------------------------------------------
  95. // locate()
  96. // liefert item mit key(item) >= y und
  97. //              und key(it)   <= key(it) fuer alle it
  98. //                                          mit key(it) >= y
  99. //         0, falls nicht existiert
  100.  
  101. bb_item bb_tree::locate(ent y)
  102.  
  103. { DPRINT(("locate %d in Baum %d\n",int(y),int(this)));
  104.   bb_item current;
  105.   if (root==0) return 0;  // by s.n
  106.   current=root;
  107.   while (!current->blatt())
  108.    { DDUMP(("current %d\n",int(current->key())));
  109.      if (cmp(y,current->key())<=0) current=current->sohn[left];
  110.      else current=current->sohn[right];   }
  111.   return (cmp(y,current->key())<=0) ? current : 0 ;
  112. }  
  113.  
  114. // -------------------------------------------------------------
  115. // located()
  116. // liefert item mit key(item) <= y und
  117. //              und key(it)   >= key(it) fuer alle it
  118. //                                       mit key(it) <= y
  119.  
  120. bb_item bb_tree::located(ent y)
  121.  
  122. { bb_item current;
  123.   if (root==0) return 0;  // by s.n
  124.   current=root;
  125.   while (!current->blatt())
  126.    if (cmp(y,current->key())<=0) current=current->sohn[left];
  127.    else current=current->sohn[right];
  128.   if (cmp(y,current->key())==0) return current;
  129.   current = current->sohn[left];
  130.   return (cmp(y,current->key())>=0) ? current : 0 ;
  131. }  
  132.  
  133. // -------------------------------------------------------------
  134. // lookup()
  135. // liefert item mit key(item)=y , falls existiert
  136. //                            0 , sonst
  137.  
  138. bb_item bb_tree::lookup(ent y)
  139.  
  140. { bb_item current = locate(y);
  141.   if (current==0) return 0;
  142.   return (cmp(y,current->key())==0) ? current : 0;
  143. }  
  144.  
  145. // -------------------------------------------------------------  
  146. // member()
  147. // liefert 1 , falls item existiert mit key(item)=y
  148. //         0 , sonst
  149.  
  150. int bb_tree::member(ent y)
  151.  
  152. { bb_item current = locate(y);
  153.   if (current==0) return 0;
  154.   return (cmp(y,current->key())==0);
  155. }  
  156.  
  157. // ------------------------------------------------------------
  158. // translate()
  159. // liefert info(item) , falls item existiert mit item = locate(y) 
  160. //                  0 , sonst
  161.  
  162. ent bb_tree::translate(ent y)
  163.  
  164. { bb_item current = locate(y);
  165.   if (current==0) return 0;
  166.   return (cmp(y,current->key())==0) ? current->inf : 0;
  167. }  
  168.  
  169. // ------------------------------------------------------------
  170. // change_obj()
  171. // liefert item mit key(item) = y und setzt info(item) auf x
  172. //                                    , falls existiert
  173. //         0                          , sonst
  174.  
  175. bb_item bb_tree::change_obj(ent y,ent x)
  176.  
  177. { bb_item current = lookup(y);
  178.   if ( current != 0 )
  179.   { current->inf = x ;  
  180.     return current; }
  181.   else return 0;
  182. }  
  183.  
  184. // ------------------------------------------------------------
  185. // search()
  186. // nachher: st = ( pk ,..., p1 ) mit 
  187. //          pk = locate(y) , p1 = root 
  188. //          p1 , ... , pk ist Suchpfad nach y
  189. // liefert inneren Knoten k mit key(k) = y , falls existiert
  190. //         0                               , sonst
  191.  
  192. bb_item bb_tree::search(ent y)
  193.  
  194. { DPRINT(("search %d in Baum %d\n",int(y),int(this)));
  195.   st.clear();
  196.   bb_item current = root;
  197.   bb_item k = 0;
  198.  
  199.   if (!root) return 0;         // Baum leer
  200.   while (!current->blatt())
  201.   { DDUMP(("current %d\n",int(current->key())));
  202.     if (cmp(y,current->key())<=0)
  203.     { if (cmp(y,current->key())==0) k=current;
  204.       st.push(current);
  205.       current = current->sohn[left];          }
  206.     else
  207.     { st.push(current);
  208.       current = current->sohn[right];         }
  209.                            }
  210.   st.push(current);
  211.   DDUMP(("Blatt %d\n",int(current->key())));
  212.   return k;
  213. }
  214.  
  215. // -----------------------------------------------------------
  216. // ord()
  217. // liefert item it mit
  218. //              |{key(it') < key(it) | it' item im Baum}| = k-1
  219. //         0 , falls kein solches item existiert
  220.     
  221. bb_item bb_tree::ord(int k)
  222.  
  223. { DPRINT(("ord %d\n",k));
  224.   if (k>anzahl || k<=0) return 0;
  225.   bb_item cur=root;
  226.   while (!cur->blatt())
  227.   { DDUMP(("ord loop k=%d key=%d\n",k,int(cur->key())));
  228.     int l=cur->sohn[left]->groesse();
  229.     if (k>l)
  230.     { k -= l;
  231.       cur=cur->sohn[right];           }
  232.     else cur=cur->sohn[left]; 
  233.   }
  234.   return cur;
  235. }
  236.     
  237. // ------------------------------------------------------------
  238. // move_iterator()
  239. // bewegt Iterator eine Stelle weiter
  240. // falls am Ende , Iterator = 0
  241.  
  242. bb_item bb_tree::move_iterator()
  243.  
  244.   { 
  245.     if (!root) 
  246.     { iterator = 0;
  247.       return 0;      }
  248.     
  249.     if (!iterator) iterator = first;
  250.     else if (iterator->sohn[right]==first) iterator = 0;
  251.      else iterator = iterator->sohn[right];
  252.     return iterator;
  253.   }
  254.     
  255. // ------------------------------------------------------------
  256. // lrot() , rrot() , ldrot() , rdrot()
  257. // Rotationen am Knoten p
  258.  
  259. void bb_tree::lrot(bb_item p, bb_item q)
  260. { DDUMP(("lrot p=%d \n",int(p->key())));
  261.   bb_item h = p->sohn[right];
  262.   p->sohn[right] = h->sohn[left];
  263.   h->sohn[left] = p;
  264.   if (!q) root=h;
  265.   else
  266.     if (cmp(p->key(),q->key())>0) q->sohn[right]=h;
  267.     else q->sohn[left]=h;
  268.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  269.   h->gr=p->groesse()+h->sohn[right]->groesse();
  270. }
  271.  
  272. void bb_tree::rrot(bb_item p, bb_item q)
  273. { DDUMP(("rrot p=%d\n",int(p->key())));
  274.   bb_item h = p->sohn[left];
  275.   p->sohn[left] = h->sohn[right];
  276.   h->sohn[right] = p;
  277.   if (!q) root=h;
  278.   else
  279.   { if (cmp(p->key(),q->key())>0) q->sohn[right] = h;
  280.     else q->sohn[left] = h; }
  281.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  282.   h->gr=p->groesse()+h->sohn[left]->groesse();
  283. }
  284.  
  285. void bb_tree::ldrot(bb_item p, bb_item q)
  286. { DDUMP(("ldrot p=%d\n",int(p->key())));
  287.   bb_item h = p->sohn[right];
  288.   bb_item g = h->sohn[left];
  289.   p->sohn[right] = g->sohn[left];
  290.   h->sohn[left] =  g->sohn[right];
  291.   g->sohn[left] = p;
  292.   g->sohn[right] = h;
  293.   if (!q) root=g;
  294.   else
  295.   { if (cmp(p->key(),q->key())>0) q->sohn[right] =g ;
  296.     else q->sohn[left] = g ; }
  297.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  298.   h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
  299.   g->gr=p->groesse()+h->groesse();
  300. }
  301.  
  302. void bb_tree::rdrot(bb_item p, bb_item q)
  303. { DDUMP(("rdrot p=%d\n",int(p->key())));
  304.   bb_item h = p->sohn[left];
  305.   bb_item g = h->sohn[right];
  306.   p->sohn[left] = g->sohn[right];
  307.   h->sohn[right] =  g->sohn[left];
  308.   g->sohn[right] = p;
  309.   g->sohn[left] = h;
  310.   if (!q) root=g;
  311.   else
  312.   { if (cmp(p->key(),q->key())>0) q->sohn[right] =g ;
  313.     else q->sohn[left] = g ; }
  314.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  315.   h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
  316.   g->gr=p->groesse()+h->groesse();
  317. }
  318.  
  319. // ------------------------------------------------------------------
  320. // sinsert()
  321. // fuegt ein neues Item (y,x) in den Baum ein
  322. //                 , falls noch kein Item it vorhanden mit key(it)=y
  323. // change_obj(y,x) ,sonst
  324. // fuellt Keller mit zu rebalancierenden Knoten 
  325. // gibt eingefuegtes Blatt zurueck
  326.  
  327.       bb_item bb_tree::sinsert(ent y,ent x=0)
  328.       { DPRINT(("sinsert %d [%d] in Baum %d\n",int(y),int(x),int(this)));
  329.     bb_item inserted;
  330.     bb_item help;
  331.  
  332.     if (!alpha) error_handler(5,"alpha nicht gesetzt");
  333.     if (iterator)  error_handler(6,"insert while tree listed");
  334.  
  335.     st.clear();                           // loesche Suchpfad
  336.  
  337.     if (!root) { DDUMP(("Baum war leer\n"));
  338.              bb_item p=new  bb_node(y,x);
  339.              p->sohn[left]=p;
  340.              p->sohn[right]=p;
  341.              root=p; 
  342.              first=p;
  343.              first->sohn[left]=first;
  344.              first->sohn[right]=first;
  345.              anzahl=1; 
  346.              inserted = p;
  347.            }
  348.     else
  349.       if (root->blatt())
  350.         if (cmp(y,root->key())<0)
  351.         { DDUMP(("links von Wurzel\n"));
  352.           bb_item p=new bb_node(y,x,Leaf,root,root);
  353.           DDUMP(("Blatt[%d] %d %d %d %d\n",(int)p,(int)p->key(),(int)p->info(),(int)p->sohn[left],(int)p->sohn[right]));
  354.           root->sohn[left]=p;
  355.           root->sohn[right]=p;
  356.           bb_item s=new bb_node(y,x,Node,p,root);
  357.           DDUMP(("Knoten[%d] %d %d %d %d\n",(int)s,(int)s->key(),(int)s->info(),(int)s->sohn[left],(int)s->sohn[right]));
  358.           first=p;
  359.           root=s;
  360.           st.push(s);
  361.           anzahl++; 
  362.           inserted = p;
  363.          }
  364.         else if (cmp(y,root->key())>0)         // hier rechts einfuegen
  365.          { DDUMP(("rechts von Wurzel\n"));
  366.            bb_item p=new bb_node(y,x,Leaf,root,root);
  367.            root->sohn[left]=p;
  368.            root->sohn[right]=p;
  369.            bb_item s=new bb_node(root->key(),root->inf,Node,root,p);
  370.            root=s;
  371.            st.push(s);
  372.            anzahl++;
  373.            inserted = p;
  374.           }
  375.          else { DPRINT(("gleicher Schluessel vorhanden\n"));
  376.             root->inf = x;
  377.             inserted = root;
  378.                }
  379.       else                           // root ist innerer Knoten
  380.       { bb_item father;
  381.         search(y);                   // fuelle Suchstack 
  382.         bb_item t=st.pop();
  383.         father = st.top();
  384.                      // einfuegen
  385.         if (cmp(y,t->key())<0)
  386.         { DDUMP(("insert links von Blatt\n"));
  387.           help = t->sohn[left];
  388.           bb_item  p = new bb_node(y,x,Leaf,help,t);
  389.           t->sohn[left]=p;
  390.           if (first==t) first=p;
  391.           help->sohn[right]=p;
  392.           bb_item s=new bb_node(y,x,Node,p,t);
  393.           if (cmp(s->key(),father->key())<=0) father->sohn[left]=s;
  394.           else father->sohn[right]=s;
  395.           anzahl++; 
  396.           inserted = p;
  397.           st.push(s);
  398.         }
  399.         else if (cmp(y,t->key())>0)     
  400.          { DDUMP(("insert rechts von Blatt -> neues Maximum\n"));
  401.            help=t->sohn[right];
  402.            bb_item p=new bb_node(y,x,Leaf,t,help);
  403.            t->sohn[right]=p;
  404.            help->sohn[left]=p;
  405.            bb_item s=new bb_node(t->key(),t->inf,Node,t,p);
  406.  
  407.            father->sohn[right] = s;
  408.            anzahl++;
  409.            inserted = p;
  410.            st.push(s);
  411.          }
  412.          else { DPRINT(("gleicher Schluessel vorhanden\n"));
  413.             t->inf = x;
  414.             st.clear();     // keine Rebalancierung notwendig
  415.             inserted = t;
  416.               }
  417.       }
  418.       return inserted;
  419.       }
  420.  
  421.  
  422. // ------------------------------------------------------------------
  423. // insert()
  424. // fuegt ein neues Item (y,x) in den Baum ein
  425. //       mittels sinsert
  426. // balanciert Baum mit ueblichen Rotationen
  427. // gibt eingefuegtes Blatt zurueck
  428.  
  429. bb_item bb_tree::insert(ent y, ent x)
  430.   bb_item inserted;
  431.   bb_item t,father;
  432.  
  433. /*
  434.   copy_key(y);
  435.   copy_inf(x);
  436. */
  437.  
  438.   inserted = sinsert(y,x);
  439.   if (!st.empty())
  440.     st.pop();                       // pop father of leaf
  441.   
  442.                     // rebalancieren
  443.   while (!st.empty())
  444.   { t=st.pop();
  445.     father = st.empty() ? 0 : st.top();
  446.     t->gr++;  
  447.     float i = t->bal();
  448.     DDUMP(("rebal cur=%d groesse=%d bal=%f\n",int(t->key()),t->groesse(),i));
  449.     if (i < alpha)
  450.       if (t->sohn[right]->bal()<=d) lrot(t,father);
  451.       else ldrot(t,father);
  452.     else if (i>1-alpha) 
  453.            if (t->sohn[left]->bal() > d ) rrot(t,father);
  454.        else rdrot(t,father);
  455.   }
  456.   DDUMP(("eingefuegtes Blatt hat key %d und info %d\n",int(inserted->key()),int(inserted->info())));
  457.   return inserted;
  458. }
  459.  
  460. // ------------------------------------------------------------------
  461. // sdel()
  462. // loescht Item it im Baum mit key(it)=y , falls existiert
  463. //         und gibt Zeiger auf it zurueck
  464. // 0 , sonst
  465. // fuellt Keller mit zu rebalancierenden Knoten
  466.  
  467. bb_item bb_tree::sdel(ent y)
  468. { DPRINT(("delete %d aus Baum %d\n",int(y),int(this)));
  469.  
  470.   if (!alpha) error_handler(5,"alpha nicht gesetzt");
  471.   if (iterator)  error_handler(6,"Baum gelistet beim Loeschen");
  472.  
  473.   st.clear();
  474.   if (root==0) return 0;                         // s.n.
  475.  
  476.   if (root->blatt())                             // Wurzel loeschen
  477.     if (cmp(y,root->key())==0)
  478.     { DDUMP(("Wurzel loeschen\n"));
  479.       bb_item p = root;
  480.       first=iterator=0;
  481.       anzahl=0; 
  482.       root=0; 
  483.       return p; 
  484.     }
  485.     else { DPRINT(("Element nicht im Baum\n"));  
  486.            return 0; }
  487.   else 
  488.   { bb_item p,father;
  489.     bb_item pp=search(y);
  490.     if (st.size()==2)                            // Sohn der Wurzel
  491.     { DDUMP(("Sohn der Wurzel loeschen\n"));
  492.       p=st.pop();
  493.       father=st.pop();
  494.  
  495.       int v1 = cmp(y,father->key());
  496.       if (cmp(y,p->key())!=0) { DPRINT(("Element nicht im Baum\n"));
  497.                               return 0; }
  498.       anzahl--;
  499.       if (v1<=0)
  500.         root=root->sohn[right];
  501.       else
  502.         root=root->sohn[left];
  503.       if (!root->blatt())
  504.       { if (first==p) first=p->sohn[right];
  505.         first->sohn[left]=p->sohn[left];
  506.         (first->sohn[left])->sohn[right]=first;
  507.       }
  508.       else
  509.       { first=root;
  510.         root->sohn[left]=root;
  511.         root->sohn[right]=root ;
  512.       }
  513.       st.push(father);
  514.       return p; 
  515.     }
  516.     else                                // Blatt mit Tiefe >= 2     
  517.     { bb_item q=st.pop();
  518.  
  519.       if (cmp(y,q->key())!=0)
  520.       { DDUMP(("Schluessel nicht vorhanden\n"));
  521.     return 0;   }
  522.  
  523.       bb_item p = st.pop();
  524.       father=st.top();
  525.       DDUMP(("Blatt %d mit Vater %d , Grossvater %d\n",int(q->key()),int(p->key()),int(father->key())));
  526.       int v2 = cmp(y,p->key());
  527.       int v1 = cmp(y,father->key());
  528.       anzahl--;
  529.       if (v1<=0)
  530.         if (v2<=0)
  531.         { father->sohn[left]=p->sohn[right];
  532.           if (first==q) { first=first->sohn[right];
  533.               q->sohn[right]->sohn[left]=first; }
  534.     }
  535.         else father->sohn[left]=p->sohn[left];
  536.       else if (v2<=0) father->sohn[right]=p->sohn[right];
  537.            else  father->sohn[right]=p->sohn[left];
  538.       q->sohn[right]->sohn[left]=q->sohn[left];
  539.       q->sohn[left]->sohn[right]=q->sohn[right];
  540.       if ( pp && (p!=pp) && p->sohn[left] )
  541.       { pp->ke = q->sohn[left]->key() ;
  542.         DPRINT(("inneren Knoten mit %d ueberschrieben und Info %d bleibt\n",int(pp->key()),int(pp->info())));
  543.       }
  544.       st.push(p);
  545.       return q;
  546.     }
  547.   }
  548. }
  549.  
  550. // ------------------------------------------------------------------
  551. // del()
  552. // loescht Item it im Baum mit key(it)=y , falls existiert
  553. //         und gibt Zeiger auf it zurueck
  554. // 0 , sonst
  555. // mittels sdel                                     
  556. // rebalanciert Baum danach
  557.  
  558. bb_item bb_tree::del(ent y)
  559. {
  560.   bb_item p,father;
  561.   bb_item deleted = sdel(y);
  562.   if (!deleted)
  563.     return 0;
  564.   if (!st.empty())
  565.     delete(st.pop());
  566.  
  567.                      // rebalancieren
  568.   while (!st.empty())
  569.   { p = st.pop();
  570.     father = st.empty() ? 0 : st.top() ;
  571.     p->gr--;              
  572.     float i=p->bal();
  573.     DDUMP(("rebal cur=%d groesse=%d bal=%f\n",int(p->key()),p->groesse(),i));
  574.     if (i<alpha)
  575.       if (p->sohn[right]->bal() <= d) lrot(p,father);
  576.       else ldrot(p,father);
  577.     else if (i>1-alpha)
  578.            if(p->sohn[left]->bal() > d) rrot(p,father);
  579.            else rdrot(p,father);
  580.   }
  581.   return deleted;
  582.  
  583. // -----------------------------------------------------------------
  584. // Gleichheitsoperator
  585. // weist this Kopie der Baumes w zu
  586.  
  587. bb_tree& bb_tree::operator=(bb_tree& w)
  588. { DDUMP(("operator = wurzel%d\n",(int)w.root->key()));
  589.   bb_item p;
  590.   bb_item l=0;
  591.   if (anzahl!=0) deltree(root); 
  592.   st.clear();
  593.   anzahl=w.anzahl;
  594.   alpha=w.alpha;
  595.   d=w.d;
  596.   iterator=0;
  597.   if (w.root)
  598.   { if (!w.root->blatt())
  599.     { p=new bb_node(w.root);
  600.       first=copytree(p,w.root,l);
  601.       first->sohn[left]=l ;
  602.       l->sohn[right]=first ; }
  603.     else
  604.     { p=new bb_node(w.root);
  605.       first=p; }
  606.     root= p;                       }
  607.   else root = 0;
  608.   DDUMP(("root=%d, first=%d\n",int(root->key()),int(first->key())));
  609.   return *this;
  610. }
  611.  
  612. bb_item bb_tree::copytree(bb_item p, bb_item q,bb_item& ll) 
  613. { DDUMP(("copytree %d\n",(int)p->key()));
  614.   bb_item a;
  615.   bb_item r;
  616.   bb_item s;
  617.   if (p->blatt())
  618.   { if (ll==0) p->sohn[left]=0;
  619.     else
  620.     { p->sohn[left]=ll;
  621.       ll->sohn[right]=p; }
  622.     p->sohn[right]=0;
  623.     a=p;
  624.     ll=p; 
  625.     DDUMP(("ll gesetzt %d\n",int(ll->key()))); }
  626.   else {
  627.     r=new bb_node(q->sohn[left]);
  628.     p->sohn[left]=r;
  629.     a=copytree(p->sohn[left],q->sohn[left],ll);
  630.     s=new bb_node(q->sohn[right]);
  631.     p->sohn[right]=s;
  632.     copytree(p->sohn[right],q->sohn[right],ll); }
  633.   return a; 
  634. }
  635.  
  636. // ------------------------------------------------------------------
  637. // Destruktoren
  638.  
  639. void bb_tree::clear()
  640. { if (root)
  641.   { DPRINT(("clear %d\n",int(root->key())));
  642.     deltree(root);
  643.    }
  644.   else DPRINT(("clear\n"));
  645.   root=0;
  646.   anzahl=0;
  647.   first=0;
  648. }
  649.  
  650. void bb_tree::deltree(bb_item p)
  651. { if (p)
  652.   { DDUMP(("deltree : current=%d\n",int(p->key())));
  653.     if (!p->blatt())
  654.     {  deltree(p->sohn[left]);
  655.        deltree(p->sohn[right]); 
  656.      }
  657.     delete(p);
  658.   }
  659. }
  660.  
  661.  
  662. void bb_tree::draw(DRAW_BB_NODE_FCT draw_node,
  663.                    DRAW_BB_EDGE_FCT draw_edge, 
  664.                    bb_node* r, 
  665.                    double x1, double x2, double y, 
  666.                    double ydist, double last_x)
  667.  double x = (x1+x2)/2;
  668.  
  669.  if (r==nil) return;
  670.  
  671.  if (last_x != 0) draw_edge(last_x,y+ydist,x,y);
  672.  
  673.  draw_node(x,y,r->key());
  674.  
  675.  if (!r->blatt()) 
  676.  { draw(draw_node,draw_edge,r->sohn[0],x1,x,y-ydist,ydist,x);
  677.    draw(draw_node,draw_edge,r->sohn[1],x,x2,y-ydist,ydist,x);
  678.   }
  679. }
  680.  
  681.  
  682. void bb_tree::draw(DRAW_BB_NODE_FCT draw_node,
  683.                    DRAW_BB_EDGE_FCT draw_edge, 
  684.                    double x1, double x2, double y, double ydist)
  685. { draw(draw_node,draw_edge,root,x1,x2,y,ydist,0); }
  686.  
  687.