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

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _rb_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. #include <LEDA/impl/rb_tree.h>
  12. //----------------------------------------------------------------------------
  13. //  rb_tree:
  14. //
  15. //  rebalancing of red black trees
  16. //
  17. //----------------------------------------------------------------------------
  18. void rb_tree::insert_rebal(rb_tree_item v)
  19. {
  20.   // preconditions:  v is new node created by insertion
  21.   //                 v != root
  22.   //
  23.   //                    u
  24.   //                    |
  25.   //                    v
  26.   //                   / 
  27.   //                  x   y
  28.   //
  29.   rb_tree_item u = v->parent;
  30.   while (u->get_bal() == red)
  31.   {
  32.     int dir = (v == u->child[left]) ? left : right;
  33.     rb_tree_item p = u->parent; 
  34.     int dir1 = (u == p->child[left]) ? left : right;
  35.     rb_tree_item w = p->child[1-dir1];
  36.     if ( w->get_bal() == red )    // p has two red children (u and w)
  37.        { u->set_bal(black);
  38.          w->set_bal(black);
  39.          if (p == root())  
  40.          { p->set_bal(black); 
  41.            break; 
  42.           }
  43.          p->set_bal(red);
  44.          v = p;
  45.          u = p->parent;
  46.         }
  47.     else 
  48.        if (dir1 == dir)      // rebalancing by one rotation
  49.          { rotation(p,u,dir1);
  50.            p->set_bal(red);
  51.            u->set_bal(black);
  52.            break;
  53.           }       
  54.        else
  55.         { double_rotation(p,u,v,dir1);
  56.           p->set_bal(red);
  57.           v->set_bal(black);
  58.           break;
  59.          }
  60.    }
  61. }
  62. void rb_tree::del_rebal(rb_tree_item w, rb_tree_item p)
  63. {
  64.   // precondition:    p is removed inner node
  65.   //                  w is remaining child of p (already linked to parent u)
  66.   //                  w != root
  67.   if (p->get_bal()==red) return;  // case 1 : nothing to do
  68.   if (w->get_bal()==red)          // case 2
  69.   { w->set_bal(black); 
  70.     return; 
  71.    } 
  72.   rb_tree_item u = w->parent;
  73.   int dir = (w == u->child[left]) ? left : right;
  74.   while (true)
  75.   {
  76.     rb_tree_item w = u->child[1-dir];
  77.   
  78.     // situation: black height of subtree rooted at black node 
  79.     // v = u->child[dir] is by one too small, w = sibling of v
  80.     //
  81.     // => increase black height of v or "move" v towards the root
  82.     //
  83.     //                          |                         |
  84.     //                          u                         u
  85.     //           dir=left:     /         dir=right:     / 
  86.     //                        /                        /   
  87.     //                       v     w                   w     v
  88.     //                            /                  / 
  89.     //                           /                  /   
  90.     //                          y     x             x     y
  91.    
  92.   
  93.     if ( w->get_bal()==black )                    // case 2: v and w are black
  94.       { rb_tree_item y = w->child[1-dir];
  95.         if ( y->get_bal()==red )                  // case 2.b 
  96.            { rotation(u,w,1-dir);
  97.              w->set_bal(u->get_bal());
  98.              u->set_bal(black);
  99.              y->set_bal(black);
  100.              break;
  101.             }
  102.         else   
  103.            if ( (y=w->child[dir])->get_bal()==red ) // case 2.c 
  104.               { double_rotation(u,w,y,1-dir);
  105.                 y->set_bal(u->get_bal());
  106.                 u->set_bal(black);
  107.                 break;
  108.               }
  109.            else 
  110.               if ( u->get_bal()==red )     // case 2.a2
  111.                  { w->set_bal(red);
  112.                    u->set_bal(black);
  113.                    break; 
  114.                   }
  115.               else                        // case 2.a1
  116.                  { rotation(u,w,1-dir);
  117.                    u->set_bal(red);
  118.                    if ( w == root() )
  119.                       break;
  120.                    else // the only non-terminating case
  121.                       { u = w->parent;
  122.                         dir = (w == u->child[left]) ? left : right;
  123.                        }
  124.                   }
  125.       }     
  126.     else                                  // case 3: v ist black, w ist red
  127.       { rb_tree_item x = w->child[dir];
  128.         rb_tree_item y;
  129.         if ( x->child[1-dir]->get_bal()==red )          // case 3.b
  130.           { double_rotation(u,w,x,1-dir);
  131.             w->child[dir]->set_bal(black);
  132.             break;
  133.            }
  134.         else 
  135.            if ( (y = x->child[dir])->get_bal()==red )   // case 3.c
  136.              { rotation(x,y,dir);
  137.                w->child[dir] = y; 
  138.                double_rotation(u,w,y,1-dir);
  139.                y->set_bal(black);
  140.                break;
  141.               }
  142.            else                                     // case 3.a 
  143.              { rotation(u,w,1-dir);
  144.                w->set_bal(black);
  145.                x->set_bal(red);
  146.                break;
  147.               }
  148.        }
  149.   
  150.    } /* end of loop */
  151. }