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

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _rb_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. //  red-black-tree ( rb-tree )
  16. //  implementation of memberfunctions
  17. //  mit verkettung der blaetter
  18.  
  19. //------------------------------------------------------------------
  20.  
  21. #include <LEDA/rb_tree.h>
  22.  
  23.  
  24. enum left_or_right { left = 0 ,right = 1, undefined = 2 };
  25.  
  26. enum colour  { node_red = 0 ,node_black = 1 ,leaf_red = 2 ,                                    leaf_black = 3 , unknown = 4 }; 
  27.  
  28. class rb_tree_node;
  29.  
  30.  
  31. rb_tree_node* rb_tree::next_item(rb_tree_node* p) const
  32. { rb_tree_node* x = p->son[right];
  33.   return (x == list_ptr) ? 0 : x;
  34.  }
  35.  
  36.  
  37. //------------------------------------------------------------------
  38. // next_smaller(x) : gibt zeiger auf den knoten mit key x zurueck
  39. // falls dieser nicht exist. sucht er den knoten mit key y , wobei
  40. // y < x und y maximal ; falls dieser auch nicht vorhanden => return 0
  41. //------------------------------------------------------------------
  42.  
  43. rb_tree_node* rb_tree::next_smaller(ent x) const
  44. {
  45.   TRACE(( "next_smaller : key : %d\n",int(x) ));
  46.  
  47.   rb_tree_node* p = get_node(x);
  48.  
  49.   if ( !p ) return 0;    // baum leer
  50.  
  51.   if ( cmp(p->k,x) <= 0 ) return p;
  52.   else if ( p != min() ) return p->son[left]; 
  53.   else return 0;
  54. }
  55.  
  56. //------------------------------------------------------------------
  57. // next_bigger(x) : gibt zeiger auf den knoten mit key x zurueck
  58. // falls dieser nicht exist. sucht er den knoten mit key y , wobei
  59. // y > x und y minimal ; falls dieser auch nicht vorhanden => return 0
  60. //------------------------------------------------------------------
  61.  
  62. rb_tree_node* rb_tree::next_bigger(ent x) const
  63. {
  64.   TRACE((" next_bigger : key : %d\n",int(x) ));
  65.  
  66.   rb_tree_node* p = get_node(x);
  67.  
  68.   if ( !p ) return 0;    // baum leer
  69.  
  70.   if ( cmp( p->k,x ) >= 0 ) return p;
  71.   else if ( p != max() ) return p->son[right];
  72.   else return 0;
  73. }
  74.  
  75. // by sn :
  76.  
  77. rb_tree_node* rb_tree::lookup(ent x) const
  78. { rb_tree_node* p = get_node(x);
  79.   if ( !p ) return 0;  
  80.   if ( cmp( p->k,x ) == 0 ) return p;
  81.   else return 0;
  82. }
  83.  
  84. void  rb_tree::change_inf(rb_tree_node* p,ent y) 
  85. { clear_inf(p->e);
  86.   copy_inf(y);
  87.   p->e = y; 
  88.  }
  89.  
  90.  
  91. //------------------------------------------------------------------
  92. // get_node1(x) : gibt pointer auf das blatt zurueck , das bei der suche
  93. //               nach dem element mit key x gefunden wird            
  94. //               falls treesize = 0 => pointer = 0
  95. // mit cmp-function
  96. //------------------------------------------------------------------
  97.  
  98.  rb_tree_node* rb_tree::get_node1(ent x) const
  99.  
  100.   TRACE(("get_node1 : key :%d\n",int(x) ));
  101.  
  102.   rb_tree_node* p;
  103.   if ( p = root)    // p:=root; if ( p != 0) continue
  104.      while ( p->is_node()  )
  105.        p =  (cmp(x,p->k) <= 0)  ? p->son[left] : p->son[right]  ; 
  106.   return p;
  107. }
  108.  
  109.  
  110. //----------------------------------------------------------------------
  111. // member(x) : true ,falls element with key x im baum , sonst 0
  112. //----------------------------------------------------------------------
  113.  
  114. int rb_tree::member(ent x) const
  115. {
  116.   TRACE(("member : key :%d\n",int(x) ));
  117.  
  118.   rb_tree_node* p = get_node(x);
  119.   return ( p  &&  ( cmp(p->k,x) == 0 ) ) ? true : false  ;
  120. }
  121.  
  122. //------------------------------------------------------------------
  123. // access(x) : gibt eintrag des elements mit key x zurueck
  124. //------------------------------------------------------------------
  125.  
  126. ent& rb_tree::access(ent x)
  127.  
  128.    TRACE(("access : key :%d\n",int(x) ));
  129.  
  130.    rb_tree_node* p = get_node(x);
  131.    if ( p  &&   ( cmp(x,p->k) == 0 ) )
  132.      return p->e;
  133.    else  error_handler(1," access(x) ,but no element with key x in tree ");
  134. }
  135.  
  136.  
  137. //----------------------------------------------------------------------
  138. // search :
  139. //----------------------------------------------------------------------
  140. // prog.34 in mehlhorn page 192
  141. // wird fuer insert und delete benoetigt . gibt Stack zurueck, worin 
  142. // pfad von wurzel zum blatt (inkl.) gespeichert ist
  143. //
  144. // search : version mit cmp-function
  145. //----------------------------------------------------------------------
  146.  
  147. rb_tree_node* rb_tree::search(ent x)
  148. {
  149.   TRACE(("search : key : %d \n",int(x) ));
  150.  
  151. // s.n.: result = inner node with key x (nil if not existing)
  152.  
  153.   rb_tree_node* result=nil;
  154.  
  155.   st.clear();
  156.  
  157.   rb_tree_node* p = root ;
  158.   if ( p )    // p:=root; if ( p != 0) continue
  159.    { while ( p->is_node() )     // else Stack remains empty
  160.         { int rel = cmp(x,p->k);
  161.           if (  rel <= 0 )
  162.                 { if (  rel == 0 ) result = p;
  163.                   push(p,left); 
  164.                   p = p->son[left];
  165.                } 
  166.            else { push(p,right); 
  167.                   p = p->son[right];
  168.                  }
  169.          }
  170.        push(p,undefined);  //leaf on the top of Stack
  171.      }
  172.   return result;
  173. }
  174.  
  175. //----------------------------------------------------------------------
  176. // pop() : private memberfunktion ( fuer insert,delete )
  177. //----------------------------------------------------------------------
  178.  
  179. void rb_tree::pop(rb_tree_node_ptr& q, int& dir1)
  180. {  
  181.    TRACE(("pop betreten : leerer keller : %s \n",                                              st.empty() ? "ja"  : "nein" ));
  182.  
  183.    stack_el z = st.pop();
  184.    q = z.nodeptr;
  185.    dir1 = z.dir;
  186.  
  187.    TRACE(("pop verlassen: key : %d :dir : %d  :leerer keller : %s \n"                   ,int(q->k),dir1, st.empty() ? "ja" : "nein"));
  188. }
  189.  
  190. //----------------------------------------------------------------------
  191. // rotation : private memberfunktion ( fuer insert,delete )
  192. //----------------------------------------------------------------------
  193.  
  194. void rb_tree::rotation(rb_tree_node* p,rb_tree_node* q, int left_right)
  195. {
  196.    TRACE(("rotation\n"));
  197.  
  198.    p->son[left_right] = q->son[1-left_right];
  199.    q->son[1-left_right] = p;
  200. }  
  201.  
  202.  
  203. //----------------------------------------------------------------------
  204. // double_rotation : private memberfunktion ( fuer insert, delete )
  205. //----------------------------------------------------------------------
  206.  
  207. void rb_tree::double_rotation(rb_tree_node* p, rb_tree_node* q, rb_tree_node* r,
  208.                               int dir1, int dir2)
  209. {
  210.    TRACE(("double_rotation\n"));
  211.  
  212.    p->son[dir1] = r->son[dir2];
  213.    q->son[dir2] = r->son[dir1]; 
  214.    r->son[dir1] =q;
  215.    r->son[dir2] =p;
  216. }
  217.  
  218. //----------------------------------------------------------------------
  219. // if_root : falls p == root => root = q
  220. //           sonst haenge q an frueheren vater von p ( den vater 
  221. //            erhaelt man durch pop )
  222. //----------------------------------------------------------------------
  223.  
  224. void rb_tree::if_root(rb_tree_node* p,rb_tree_node* q)
  225.   TRACE(( "if_root \n"));
  226.  
  227.   int dir;
  228.  
  229.   if ( p == root ) root = q;
  230.   else {
  231.          TRACE((" if_root :Stacksize ist %d\n", st.size() ));
  232.          pop(p,dir);
  233.          p->son[dir] = q;
  234.        }
  235. }
  236.  
  237. //----------------------------------------------------------------------
  238. // insert(x,y) : prog. 35/36/37 in mehlhorn seite 193     
  239. // fuegt element mit key x und entry y ein
  240. // gibt zeiger auf eingefuegten knoten zurueck
  241. //----------------------------------------------------------------------
  242.  
  243. rb_tree_node* rb_tree::insert( ent x, ent y)
  244. {  
  245.    TRACE(("insert : key = %d \n" , int (x) ));
  246.  
  247.    copy_key(x);
  248.    copy_inf(y);
  249.  
  250.    rb_tree_node* q = new rb_tree_node(x,y,leaf_black,0,0);
  251.    rb_tree_node* r = new rb_tree_node;
  252.    rb_tree_node* p; 
  253.    rb_tree_node* back = q;  // wird von insert zurueckgegeben
  254.    int dir1,dir2;
  255.  
  256.    ++ counter;
  257.  
  258.    if ( !root ) 
  259.    { 
  260.      delete r;
  261.      list_ptr = root = q;
  262.      root->son[right] = root->son[left] = root;  // verkettung
  263.      return back ;
  264.    }
  265.  
  266.    search(x);       // danach steht im Stack st der suchpfad
  267.  
  268.    pop(p,dir1);
  269.  
  270.    if ( cmp(p->k,x) == 0 )  
  271.                                       // falls element mit gleichem
  272.    {                                  // key exist. => ueberschreiben
  273.      delete r;
  274.      delete q;
  275.      --counter;
  276.      p->e = y;
  277.      return p;
  278.    }
  279.  
  280.    r->gets_red_node();
  281.    if ( cmp(x,p->k) < 0 )
  282.       { r->k = x;
  283.         r->son[left] = q;
  284.         r->son[right]= p;
  285.  
  286.        q->son[left] = p->son[left];   // verkettung
  287.        q->son[right] = p;
  288.        p->son[left]->son[right] = q;
  289.        p->son[left] = q;
  290.        if ( p == list_ptr ) list_ptr = q;     
  291.                 // p->key war minimum , x neues minimum
  292.            
  293.       }
  294.     else 
  295.       { r->k = p->k;
  296.         r->son[left] = p;
  297.         r->son[right]= q;
  298.  
  299.         q->son[left] = p;            // verkettung
  300.         q->son[right] = p->son[right];
  301.         p->son[right]->son[left] = q;
  302.         p->son[right] = q;
  303.       }
  304.  
  305.     if ( st.empty() )      //  baum vor einfuegen einelementig
  306.       { 
  307.         r->gets_black_node();
  308.         root = r;
  309.         p->son[right] = p->son[left] = q;  // verkettung
  310.         return back ;
  311.       }
  312.  
  313.     pop(q,dir2);
  314.     q->son[dir2] = r;
  315.     if ( q->is_black() ) return back; // end of prog.35 in mehlhorn
  316.     
  317.     while (1)
  318.     {
  319.       pop(p,dir1);
  320.  
  321.       if ( p->son[1-dir1]->is_red() ) //p hat 2 rote soehne=> farbtausch
  322.      { 
  323.        p->son[left]->gets_black_node();
  324.            p->son[right]->gets_black_node();
  325.        p->gets_red_node();
  326.        if ( p == root )  { p->gets_black_node(); return back; }
  327.        r = p;
  328.        pop(q,dir2);
  329.        if ( q->is_black() )  return back;
  330.          }
  331.       else if (dir1 == dir2)      // rebalancieren  durch eine rotation
  332.         {
  333.           rotation(p,q,dir1);
  334.       p->gets_red_node();
  335.       q->gets_black_node();
  336.           if_root(p,q);     
  337.       return back;
  338.         }       
  339.       else
  340.     {
  341.       double_rotation(p,q,r,dir1,dir2);
  342.       p->gets_red_node();
  343.       r->gets_black_node();
  344.           if_root(p,r);     
  345.       return back;
  346.     }
  347.     }
  348. }
  349. //----------------------------------------------------------------------
  350. // end of insert
  351. //----------------------------------------------------------------------
  352.  
  353.  
  354. //----------------------------------------------------------------------
  355. // del(x) :
  356. // loescht element mit key x und gibt entry dieses elements zurueck,
  357. // falls ein solches existiert , sonst 0 .
  358. //----------------------------------------------------------------------
  359.  
  360. void rb_tree::del(ent x)
  361. {
  362.   TRACE(("del : %d \n",int(x) ));
  363.  
  364.   rb_tree_node_ptr u,v,w,p,x1,y;
  365.   int dir1,dir2;
  366.  
  367.   if ( !root ) return; // error_handler(2, " del , but treesize = 0 ");
  368.  
  369.  
  370.   rb_tree_node* pp = search(x);  // danach im Stack st der suchpfad gespeichert 
  371.                                  // pp ist innerer Knoten mit Kopie von x
  372.                                  // (nil, falls keiner existiert)
  373.   
  374.   
  375.   pop(v,dir1);
  376.  
  377.   if ( cmp(v->k,x) != 0 ) return;   // x nicht gefunden: nichts zu tun
  378.  
  379.  
  380.   -- counter;
  381.  
  382.   rb_tree_node* back = v;  // back ist zu entfernendes Blatt
  383.  
  384.   if ( v == root )                                     // treesize = 1
  385.      {
  386.        root = list_ptr = 0;
  387.        clear_key(back->k);
  388.        clear_inf(back->e);
  389.        delete back;
  390.        return;
  391.      } 
  392.  
  393.   //s.n.: overwrite possible copy of x in inner node pp
  394.  
  395.   if (pp && v->son[left]) pp->k = v->son[left]->k;
  396.  
  397.  
  398.   if ( v == list_ptr ) list_ptr = v->son[right];
  399.   v->son[left]->son[right] = v->son[right];           // verkettung
  400.   v->son[right]->son[left] = v->son[left];
  401.   
  402.   pop(u,dir1);
  403.   if (st.empty() )                                      // u = root
  404.      {
  405.        root = u->son[1-dir1];
  406.        if ( root->is_node() )      // tree hat zwei blaetter
  407.          root->gets_black_node();
  408.        else                       // tree besteht nur noch aus root
  409.      root->gets_black_leaf();
  410.  
  411.        delete(u);
  412.        clear_key(back->k);
  413.        clear_inf(back->e);
  414.        delete back;
  415.        return;
  416.      }
  417.  
  418.   pop(p,dir2);
  419.   w = u->son[1-dir1];
  420.   p->son[dir2] = w;
  421.   if (u->is_red() || w->is_red() )    // situation 1 , 2
  422.     { 
  423.       TRACE(( " situation 1,2 \n " ));
  424.  
  425.       if ( w->is_red() ) w->gets_black_node(); 
  426.       delete(u);
  427.       clear_key(back->k);
  428.       clear_inf(back->e);
  429.       delete back;
  430.       return; 
  431.     } 
  432.   delete(u);
  433.  
  434.   // situation 3 : schwarztiefe des unterbaums mit wurzel v um 
  435.   //               zu niedrig
  436.   //  =>  tiefe im unterbaum mit wurzel v um 1 erhoehen 
  437.   //      bzw. v wandert weiter nach oben
  438.   // bem: u ist vater von v , w der bruder von v
  439.  
  440. v = w;
  441. u = p;
  442. dir1 = dir2;
  443.   while(1)
  444. {
  445.   w = u->son[1-dir1];
  446.   if ( w->is_black() )              // fall2 , v und bruder w sind black
  447.   {  if ( w->son[1-dir1]->is_red() )  // fall 2.b 
  448.         {
  449. TRACE((" 2b \n"));
  450.             rotation(u,w,1-dir1);
  451.         w->c = u->col();
  452.         u->gets_black_node();
  453.         (w->son[1-dir1])->gets_black_node();
  454.         if_root(u,w);
  455.             clear_key(back->k);
  456.             clear_inf(back->e);
  457.             delete back;
  458.         return;
  459.         }
  460.      else   if ( ( y = w->son[dir1] )->is_red() ) // 2.c 
  461.         { 
  462. TRACE((" 2c \n"));
  463.         double_rotation(u,w,y,1-dir1,dir1);
  464.         y->c = u ->col();
  465.         u->gets_black_node();
  466.         if_root(u,y);
  467.             clear_key(back->k);
  468.             clear_inf(back->e);
  469.             delete back;
  470.         return;
  471.         }
  472.      else if ( u->is_red() )     // fall 2.a2
  473.     {
  474. TRACE((" 2a2 \n"));
  475.         w->gets_red_node();
  476.         u->gets_black_node();
  477.             clear_key(back->k);
  478.             clear_inf(back->e);
  479.             delete back;
  480.             return; 
  481.     }
  482.      else {                      // fall 2.a1
  483. TRACE((" 2a1 \n"));
  484.         rotation(u,w,1-dir1);
  485.         u->gets_red_node();
  486.         if ( u == root )
  487.              { 
  488. TRACE((" 2a1 nicht ende\n"));
  489.            root = w ;
  490.                    clear_key(back->k);
  491.                    clear_inf(back->e);
  492.                    delete back;
  493.            return;
  494.                  }
  495.         else {
  496. TRACE((" 2a1  ende\n"));
  497.            pop(u,dir1);
  498.            u->son[dir1] = w;
  499.            v = w;
  500.                  }
  501.             // einziger fall , der nicht sofort (d.h.nach einfach- 
  502.         // oder doppelrotation) terminiert ; v wandert zur wurzel
  503.           }
  504.   }     
  505. else                      // fall 3 ; v ist black, w ist red
  506.   { x1 = w->son[dir1];
  507.     if ( x1->son[1-dir1]->is_red() )              // fall 3.b
  508.       { 
  509. TRACE((" 3b \n"));
  510.         double_rotation(u,w,x1,1-dir1,dir1);
  511.         w->son[dir1]->gets_black_node();
  512.     if_root(u,x1);
  513.         clear_key(back->k);
  514.         clear_inf(back->e);
  515.         delete back;
  516.         return;
  517.       }
  518.     else if ( ( y = x1->son[dir1] )->is_red() )   // fall 3.c
  519.       {
  520. TRACE((" 3c \n"));
  521.         rotation(x1,y,dir1);
  522.         w->son[dir1] = y; 
  523.     double_rotation(u,w,y,1-dir1,dir1);
  524.         y->gets_black_node();
  525.     if_root(u,y);
  526.         clear_key(back->k);
  527.         clear_inf(back->e);
  528.         delete back;
  529.     return;
  530.       }
  531.     else                                         // fall 3.a 
  532.       { 
  533. TRACE((" 3a \n"));
  534.         rotation(u,w,1-dir1);
  535.     w->gets_black_node();
  536.     x1->gets_red_node ();
  537.     if_root(u,w);
  538.         clear_key(back->k);
  539.         clear_inf(back->e);
  540.         delete back;
  541.     return;
  542.       }
  543.   }  // end of fall 1,2,3
  544. } // end of while(1)
  545. } // end of del
  546.  
  547.  
  548. //------------------------------------------------------------------
  549. // operator=
  550. //------------------------------------------------------------------
  551.  
  552. rb_tree& rb_tree::operator=(const rb_tree& t)
  553. {
  554.   TRACE(( " operator= \n"));
  555.  
  556.    if (this == &t) return *this;
  557.  
  558.    clear();
  559.  
  560.    if ( t.root )   
  561.    { rb_tree_node* pre = 0;
  562.      root = t.copy_tree(t.root,pre);
  563.      list_ptr = root;
  564.      while (list_ptr->son[left]) list_ptr = list_ptr->son[left];
  565.      list_ptr->son[left] = pre;
  566.      pre->son[right] = list_ptr;
  567.      counter = t.counter;
  568.    }
  569.  
  570.    return *this; 
  571. }
  572.  
  573. //------------------------------------------------------------------
  574. // rb_tree(rb_tree&) constructor :
  575. //------------------------------------------------------------------
  576.  
  577.   rb_tree::rb_tree(const rb_tree& t)  : st(32)
  578.   { root  = list_ptr = 0 ;
  579.     if ( t.root ) 
  580.     { rb_tree_node* pre = 0;
  581.       root = t.copy_tree(t.root,pre);
  582.       list_ptr = root;
  583.       while (list_ptr->son[left]) list_ptr = list_ptr->son[left];
  584.       list_ptr->son[left] = pre;
  585.       pre->son[right] = list_ptr;
  586.       counter = t.counter; 
  587.      }
  588.   }
  589.  
  590. //------------------------------------------------------------------
  591. // copy_tree(p) kopiert baum mit wurzel p und gibt pointer auf wurzel
  592. // der kopie zurueck. pre enthaelt letztes erzeugtes Blatt ( Blaetter 
  593. // werden von links nach rechts erzeugt!
  594. //------------------------------------------------------------------
  595.  
  596. rb_tree_node* rb_tree::copy_tree( rb_tree_node* p, rb_tree_node_ptr& pre) const
  597. {
  598.   rb_tree_node* q = new rb_tree_node(p);  // q = p
  599.  
  600.   if ( p->is_node() )  // internal node: copy subtrees 
  601.   {
  602.     q->son[left] = copy_tree(p->son[left],pre);
  603.     q->son[right] = copy_tree(p->son[right],pre);
  604.   }
  605.   else   //leaf: chaining with last created leaf "pre"
  606.   {
  607.     copy_key(q->k);
  608.     copy_inf(q->e);
  609.  
  610.     if (pre) pre->son[right] = q; 
  611.     q->son[left] = pre;
  612.     pre = q;
  613.  
  614.    }
  615.  
  616.   return q;
  617. }
  618.  
  619. //------------------------------------------------------------------
  620. // clear
  621. //------------------------------------------------------------------
  622.  
  623. void rb_tree::clear() 
  624. {
  625.    TRACE(( " clear \n"));
  626.  
  627.    st.clear();
  628.  
  629.    if ( root )
  630.    {
  631.      del_tree(root);
  632.      root = list_ptr = 0;
  633.      counter = 0;
  634.    }
  635. }
  636.  
  637. //------------------------------------------------------------------
  638. // del_tree(p) : loeschen des unterbaums mit wurzel p
  639. //------------------------------------------------------------------
  640.  
  641. void rb_tree::del_tree(rb_tree_node* p)
  642. {
  643.   TRACE(("del_tree : nodekey :%d \n",int(p->k) ));
  644.  
  645.   if ( p->is_node() )
  646.   { del_tree(p->son[left]);
  647.     del_tree(p->son[right]);
  648.    }
  649.   else
  650.   { clear_key(p->k);
  651.     clear_inf(p->e);
  652.    }
  653.  
  654.   delete(p);
  655. }
  656.  
  657. //-----------------------------------------------------------------
  658. // test auf schwarztiefe und bildhafte darstellung des baums nur
  659. // im Trace-modus moeglich
  660. //-----------------------------------------------------------------
  661.  
  662. #ifdef TEST1
  663.  
  664. int rb_tree::deep_test(rb_tree_node* p) const
  665. {
  666.   if ( p->is_node() )
  667.   {
  668.     int i = deep_test(p->son[left]);
  669.     if ( i && i == deep_test( p->son[right] ) )
  670.         // falls i=0  => fehler im  linken sohn
  671.         return ( p->is_black() ? i+1  : i ) ;
  672.     else return false ;    // fehler => return false = 0
  673.   }
  674.   else return 1;           // p ist blatt ( immer black )      
  675. }
  676.  
  677. int rb_tree::black_deep_test() const
  678. {
  679.   if ( root )    // falls treesize > 0
  680.     return ( deep_test(root) ? true : false ) ;
  681.   else return true;
  682. }
  683.  
  684. //------------------------------------------------------------------
  685. // print()    : ausgeben des rb_trees ( um 90 grad gedreht )
  686. //              nur fuer type = int  
  687. // print_tree(p) : ausgeben des unterbaums mit wurzel p
  688. //------------------------------------------------------------------
  689.  
  690. void rb_tree::print_tree(rb_tree_node* p,int h) const
  691. {  
  692.        if ( p->is_node() ) print_tree(p->son[right],h+1);
  693.  
  694.        for( int j=1; j <= h ; j++ ) cout << "     ";
  695.  
  696.        switch (p->col())   {
  697.           case node_black   : cout << " b "; break;
  698.           case leaf_black   : cout << " b "; break;
  699.           case node_red     : cout << " r "; break;
  700.           case leaf_red     : cout << " r "; break;
  701.           case unknown      : cout << " u "; break;
  702.           default           : cout << " ? "; break;
  703.        }
  704.        cout << int(key(p)) ;
  705.        if ( p->is_leaf() )
  706.        {
  707.          cout << string(" succ : %d",int(key(p->son[right]))) ;
  708.          cout << string(" pred : %d\n",int(key(p->son[left]))) ;
  709.        }
  710.        else cout << "\n";
  711.  
  712.        if ( p->is_node() ) print_tree(p->son[left],h+1);
  713. }
  714.  
  715. void rb_tree::print() const
  716. {
  717.   cout << "tree.size : " << size() << "\n";
  718.   if ( root ) print_tree(root,1);
  719. }
  720.         
  721. #endif TEST1
  722.  
  723.  
  724. void rb_tree::draw(DRAW_RB_NODE_FCT draw_red_node,
  725.                    DRAW_RB_NODE_FCT draw_black_node,
  726.                    DRAW_RB_EDGE_FCT draw_edge, 
  727.                    rb_tree_node* r, 
  728.                    double x1, double x2, double y, 
  729.                    double ydist, double last_x)
  730.  
  731.  double x = (x1+x2)/2;
  732.  
  733.  if (r==nil) return;
  734.  
  735.  if (last_x != 0) draw_edge(last_x,y+ydist,x,y);
  736.  
  737.  if (r->is_red()) 
  738.     draw_red_node(x,y,r->k);
  739.  else 
  740.     draw_black_node(x,y,r->k);
  741.  
  742.  if (r->is_node()) 
  743.  { draw(draw_red_node,draw_black_node,draw_edge,r->son[0],x1,x,y-ydist,ydist,x);
  744.    draw(draw_red_node,draw_black_node,draw_edge,r->son[1],x,x2,y-ydist,ydist,x);
  745.   }
  746. }
  747.  
  748.  
  749. void rb_tree::draw(DRAW_RB_NODE_FCT draw_red_node,
  750.                    DRAW_RB_NODE_FCT draw_black_node, 
  751.                    DRAW_RB_EDGE_FCT draw_edge, 
  752.                    double x1, double x2, double y, double ydist)
  753. { draw(draw_red_node,draw_black_node,draw_edge,root,x1,x2,y,ydist,0); }
  754.  
  755.  
  756. //------------------------------------------------------------------
  757. // end of rb_tree.c
  758. //------------------------------------------------------------------
  759.