_bb1_tree.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:19k
开发平台:

MultiPlatform

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