home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ledar34.zip / leda-r-3_4_tar / LEDA-3.4 / src / dict / _rb_tree.c < prev    next >
C/C++ Source or Header  |  1996-09-03  |  5KB  |  186 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA 3.4
  4. +
  5. +  _rb_tree.c
  6. +
  7. +  This file is part of the LEDA research version (LEDA-R) that can be 
  8. +  used free of charge in academic research and teaching. Any commercial
  9. +  use of this software requires a license which is distributed by the
  10. +  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
  11. +  (fax +49 681 31104).
  12. +
  13. +  Copyright (c) 1991-1996  by  Max-Planck-Institut fuer Informatik
  14. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  15. +  All rights reserved.
  16. *******************************************************************************/
  17. #include <LEDA/impl/rb_tree.h>
  18.  
  19.  
  20. //----------------------------------------------------------------------------
  21. //  rb_tree:
  22. //
  23. //  rebalancing of red black trees
  24. //
  25. //  S. N"aher (1993)
  26. //----------------------------------------------------------------------------
  27.  
  28.  
  29. void rb_tree::insert_rebal(rb_tree_item v)
  30. {
  31.   // preconditions:  v is new node created by insertion
  32.   //                 v != root
  33.   //
  34.   //                    u
  35.   //                    |
  36.   //                    v
  37.   //                   / \ 
  38.   //                  x   y
  39.   //
  40.  
  41.   rb_tree_item u = v->parent;
  42.  
  43.   root()->set_bal(black);
  44.  
  45.   while (u->get_bal() == red)
  46.   {
  47.     int dir = (v == u->child[left]) ? left : right;
  48.  
  49.     rb_tree_item p = u->parent; 
  50.     int dir1 = (u == p->child[left]) ? left : right;
  51.  
  52.     rb_tree_item w = p->child[1-dir1];
  53.  
  54.     if ( w->get_bal() == red )    // p has two red children (u and w)
  55.        { u->set_bal(black);
  56.          w->set_bal(black);
  57.          if (p == root())  
  58.          { p->set_bal(black); 
  59.            break; 
  60.           }
  61.          p->set_bal(red);
  62.          v = p;
  63.          u = p->parent;
  64.         }
  65.     else 
  66.        if (dir1 == dir)      // rebalancing by one rotation
  67.          { rotation(p,u,dir1);
  68.            p->set_bal(red);
  69.            u->set_bal(black);
  70.            break;
  71.           }       
  72.        else
  73.         { double_rotation(p,u,v,dir1);
  74.           p->set_bal(red);
  75.           v->set_bal(black);
  76.           break;
  77.          }
  78.    }
  79.  
  80. }
  81.  
  82.  
  83.  
  84. void rb_tree::del_rebal(rb_tree_item w, rb_tree_item p)
  85. {
  86.   // precondition:    p is removed inner node
  87.   //                  w is remaining child of p (already linked to parent u)
  88.   //                  w != root
  89.  
  90.  
  91.  
  92.   if (p->get_bal()==red) return;  // case 1 : nothing to do
  93.  
  94.   if (w->get_bal()==red)          // case 2
  95.   { w->set_bal(black); 
  96.     return; 
  97.    } 
  98.  
  99.  
  100.   root()->set_bal(black);
  101.  
  102.   rb_tree_item u = w->parent;
  103.   int dir = (w == u->child[left]) ? left : right;
  104.  
  105.   while (true)
  106.   {
  107.     rb_tree_item w = u->child[1-dir];
  108.   
  109.     // situation: black height of subtree rooted at black node 
  110.     // v = u->child[dir] is by one too small, w = sibling of v
  111.     //
  112.     // => increase black height of v or "move" v towards the root
  113.     //
  114.     //                          |                         |
  115.     //                          u                         u
  116.     //           dir=left:     / \        dir=right:     / \
  117.     //                        /   \                     /   \
  118.     //                       v     w                   w     v
  119.     //                            / \                 / \
  120.     //                           /   \               /   \
  121.     //                          y     x             x     y
  122.    
  123.   
  124.     if ( w->get_bal()==black )                    // case 2: v and w are black
  125.       { rb_tree_item y = w->child[1-dir];
  126.         if ( y->get_bal()==red )                  // case 2.b 
  127.            { rotation(u,w,1-dir);
  128.              w->set_bal(u->get_bal());
  129.              u->set_bal(black);
  130.              y->set_bal(black);
  131.              break;
  132.             }
  133.         else   
  134.            if ( (y=w->child[dir])->get_bal()==red ) // case 2.c 
  135.               { double_rotation(u,w,y,1-dir);
  136.                 y->set_bal(u->get_bal());
  137.                 u->set_bal(black);
  138.                 break;
  139.               }
  140.            else 
  141.               if ( u->get_bal()==red )     // case 2.a2
  142.                  { w->set_bal(red);
  143.                    u->set_bal(black);
  144.                    break; 
  145.                   }
  146.               else                        // case 2.a1
  147.                  { rotation(u,w,1-dir);
  148.                    u->set_bal(red);
  149.                    if ( w == root() )
  150.                       break;
  151.                    else // the only non-terminating case
  152.                       { u = w->parent;
  153.                         dir = (w == u->child[left]) ? left : right;
  154.                        }
  155.                   }
  156.       }     
  157.     else                                  // case 3: v ist black, w ist red
  158.       { rb_tree_item x = w->child[dir];
  159.         rb_tree_item y;
  160.         if ( x->child[1-dir]->get_bal()==red )          // case 3.b
  161.           { double_rotation(u,w,x,1-dir);
  162.             w->child[dir]->set_bal(black);
  163.             break;
  164.            }
  165.         else 
  166.            if ( (y = x->child[dir])->get_bal()==red )   // case 3.c
  167.              { rotation(x,y,dir);
  168.                w->child[dir] = y; 
  169.                double_rotation(u,w,y,1-dir);
  170.                y->set_bal(black);
  171.                break;
  172.               }
  173.            else                                     // case 3.a 
  174.              { rotation(u,w,1-dir);
  175.                w->set_bal(black);
  176.                x->set_bal(red);
  177.                break;
  178.               }
  179.        }
  180.   
  181.    } /* end of loop */
  182.  
  183. }
  184.  
  185.