红黑树(转)

 

http://liyiwen.javaeye.com/blog/345799

满足下面几个条件的二叉搜索树,称为红黑树:

1.       任何一个节点都被着色――红色或是黑色。

2.       根节点是黑色的。

3.       所有的NIL节点都看成黑色(NIL节点是就是一个假想的或是无实在意义的节点,所有应该指向NULL的指针,都看成指向了NIL节点。包括叶节点的子节点指针或是根节点的父指针)。

4.       如果一个节点是红色的,那么它的子节点一定是黑色的。

5.       对于任何一个节点而言,从该节点到它的子孙节点中的NIL节点路径中,所包含的黑节点个数相同。

 

黑高度的定义:

从任何一个节点,向下到底部的路径中,包含的黑节点的个数,称为这个节点的黑高度。从红黑树的第5条性质可以看出,黑高度是唯一的、确定的。

 

只要同时满足红黑树的这些条件,就一定会有“红黑树可以保证任何两条从根部到树叶的路径节点个数相差不超过2倍”这个平衡的性质。

我们可以假设,如果存在两条路径LSLS长两倍以上(S路径上有n个节点,L上有大于2n个节点)。可知,S的黑高度最大只可能是n,那么根据第5条性质,L的黑高度也大也只可能是n,也就是,L路径上一定有超过n个红色节点(因为节点不是黑的就必定是红的)。所以,肯定会有两个以上的红色节点是相邻的。这就与第4个条件矛盾了。所以,红黑树可以保证任何两条从根部到树叶的路径节点个数相差不超过2倍。

 

红黑树的高度h<2lg(n+1)(这个在《算法导论》13.1节中有证明)。也就是说,红黑树的操作的时间复杂度是O(lgn)的。 

 

二叉搜索树的操作时间复杂度,取决于树高h,因此,我们当然就希望h尽量地小以提高操作的效率。从直观上就可以发现,二叉搜索树各子树的规模越平均,它的高度就会越小。所以在应用中,一般都会将二叉搜索树实现成一种平衡树,以保证最差时间复杂度为O(lgn)。红黑树就是其中的一种,应用得很广泛(SGI STL的set和map就是基于红黑树来实现,Linux内核中也用到这个数据结构

红黑树是二叉搜索树的一种。它与普通二叉搜索树不同的是,红黑树的每个节点都附加了另一个属性――颜色,可以是红色,也可以是黑色。通过对于每条路径上节点颜色的规则进行限定,红黑树可以保证任何两条从根部到树叶的路径节点个数相差不超过2倍。所以,红黑树是一种近似平衡的二叉搜索树。

 

 

红黑树的查找、最大值、最小值、前趋、后继等操作,与普通的二叉搜索树没有什么区别。插入和删除操作需要重新实现。仅仅用普通的二叉搜索树的插入和删除动作,可能会破坏红黑树本身的一些性质,因此,需要进行额外的处理。这些额外的处理主要是改变树节点的颜色,或是改变树的结构。

 

 

 

 

 

 

 

 

 

 

树的旋转

改变树的结构,主要是用旋转。旋转有两种,左旋和右旋,下面是这两种旋转的: 

这种旋转的操作,是在二叉搜索树的局部对树的结构进行调整的一种方式,经过旋转之后,二叉搜索树的性质是不会发生改变的。如下图:

 

向红黑树插入节点,先将需要插入的节点着成红色,用普通二叉搜索树的方法将这个节点插入到树中,然后再想办法把被破坏的红黑性质恢复。(将新插入的节点颜色着成红色,呆以尽量减少对红黑性质的破坏,恢复起来也容易。因为插入红色节点的话,那么被破坏的部分会在局部,考虑的问题也就比较少,恢复过程也容易形成递归,详细见下文说明)

我们考虑下,如果一个红色节点(下文称用Z指向它)被插入到树中,那么有哪些红黑性质可能被破坏呢?只有第2条(根节点是黑色的)以及第4条(红色节点的子节点一定是黑色节点),其它都不会被破坏。

如果插入的节点的父节点是黑色的,那么不需要做任何调整,这红黑树是正常的。如果父节点是红色,或没有父节点(也就是插在了树根的位置),那么就要进行调整以保证红黑树是正确的。

首先对第条进行分析,我们知道,插入一个新的节点,这个节点肯定会被放到树的底部成为一个叶节点(参考普通二叉树的插入过程),那么这个红色节点就没有可能和自己的子节点同色(因为叶节点的子节点是NIL节点,都是黑色的),如果第4条被破坏的话,肯定是Z指向的节点的父节点是红色的。因此,为了使分析和解决更加容易和清晰,我们在对树进行调整以恢复红黑特性时,始终使得Z总是指向相邻红色的节点中的子节点(指针Z可能会向上升到树的中部或根部)。基于这个做法,我们可以知道,如果是第2条被破坏了的话,也就是Z指向根节点了,那么第4条肯定就符合了(因为Z的父节点是NIL,黑色的),因此对第2条性质的恢复变得很简单,只需要被根从红色变为黑色即可。这时,所有性质都会被满足了(因为是根节点,所以根节点被着为黑色时,所有路径都黑高会统一加1,也就是第5条不会被破坏,操作之后的红黑树仍然是正确的)。好了,现在只留下第4条性质的恢复的问题了。

如果第4条被破坏了,也就是说,Z的父节点是红色的,那么,说明,Z一定有祖父节点,而且是黑色的(否则插入前原树就有问题,又或是调整时的方法不正确)。因此可以把问题放到以Z的祖父节点为根节点的子树内进行解决,这样可以把调整的范围最小化,而且这也是有可能的:只要不改变这子树的黑高度,那么就不会对树的其它部分产生影响。我们要做的就是在这个子树范围内把红黑性质调整回来。再看子树的根是否与其父节点同为红色,是的话,就再次用前面所说的去解决它,一直向上递归到红黑性质被恢复为止。

 

红黑树的节点插入 

 

  对第4条性质的恢复,根据Z的父节点是Z的祖节点的左子节点还是右子节点,分为两组对称的情况,每组有3种情况。下面我们只对其中一组进行说明,以Z的父节点是Z祖节点的左子节点为例:  

RBT-Insert3

第一种:Z的“叔父”节点是红色。

 

             RBTree1 

 

如上图所示,在这种情况下,将父、叔节点都着为黑色,再将子树根节点着为红色,那么子树的黑高度没有发生改变,而且红黑性质得得到了调整。此时,再将Z指向子树的根节点,向上递归恢复红黑特性。

 

第二种:Z的“叔父”节点是黑色的,Z的父节点的左子节点。

如上图,将Z的父节点与祖节点进行一次右旋,并把父节点着黑色,原来的祖节点着红色。这些子树的红黑特性得到了恢复,而且子树的黑高度没有变化。另外,由于子树根节点已经是黑色了(这个节点不会出现父子同为红色的问题了),所以不必再向上递归了,此时整个树的红黑特性都已经是正确的了。

 

第三种:Z的“叔父”节点是黑色的,Z的父节点的右子节点。

 

 

RBTree2

 

 

 

如上图,将Z本身与其父节点进行一次左旋,让Z指向原来的父节点,就可以调整为情况二,而情况二已经得到解决。

这样,红黑树的节点插入问题就得到了解决。

 

 

第二部分

 

 

红黑树的节点删除

 

从红黑树上删除一个节点,可以先用普通二叉搜索树的方法,将节点从红黑树上删除掉,然后再将被破坏的红黑性质进行恢复。

我们回忆一下普通二叉树的节点删除方法:Z指向需要删除的节点,Y指向实质结构上被删除的结点,如果Z节点只有一个子节点或没有子节点,那么Y就是指向Z指向的节点。如果Z节点有两个子节点,那么Y指向Z节点的后继节点(其实前趋也是一样的),而Z的后继节点绝对不可能有左子树。因此,仅从结构来看,二叉树上实质被删除的节点最多只可能有一个子树。

现在我们来看红黑性质的恢复过程:

如果Y指向的节点是个红色节点,那么直接删除掉Y以后,红黑性质不会被破坏。操作结束。

如果Y指向的节点是个黑色节点,那么就有几条红黑性质可能受到破坏了。首先是包含Y节点的所有路径,黑高度都减少了一(第5条被破坏)。其次,如果Y的有红色子节点,Y又有红色的父节点,那么Y被删除后,就出现了两个相邻的红色节点(第4条被破坏)。最后,如果Y指向的是根节点,而Y的子节点又是红色的,那么Y被删除后,根节点就变成红色的了(第2条被破坏)。

其中,第5条被破坏是让我们比较难受的。因为这影响到了全局。这样动作就太大太复杂了。而且在这个条件下,进行其它红黑性质的恢复也很困难。所以我们首先解决这个问题:如果不改变含Y路径的黑高度,那么树的其它部分的黑高度就必须做出相应的变化来适应它。所以,我们想办法恢复原来含Y节点的路径的黑高度。做法就是把Y节点的黑色,推到它的子节点X上去。(X可能是NIL节点)。这样,X就可能具有双重黑色,或是同时具有红黑两色,也就是第1条性质被破坏了。

但第1条性质是比较容易恢复的:一、如果X是同时具有红黑两色,那么好办,直接把X涂成黑色,就行了。而且这样把所有问题都解决了。因为将X变为黑色,2、4两条如果有问题的话也会得到恢复。二、如果X是双黑色,那么我们希望把这种情况向上推一直推到根节点(调整树结构和颜色,X的指向新的双黑色节点,X不断向上移动),让根节点具双黑色,这时,直接把X的一层黑色去掉就行了(因为根节点被包含在所有的路径上,所以这样做所有路径同时黑高减少一,不会破坏红黑特征)。

下面就具体地分析如何恢复1、2、4三个可能被破坏的红黑特性:我们知道,如果X指向的节点是有红黑两色,或是X是根节点时,只需要简单的对X进行一些改变就行了。要对除X节点外的其它节点进行操作时,必定是这样的情况:X节点是双层黑色,且X有父节点P。由知可知,X必然有兄弟节点W,而且这个W节点必定有两个子节点。(因为这是原树满足红黑条件要求而自然具备的。X为双黑色,那么P的另一个子节点以下一定要有至少两层的节点,否则高黑度不可能和X路径一致)。所以我们就分析这些节点之间如何变形,把问题限制在比较小的范围内解决。另一个前提是:X在一开始,肯定是树底的叶节点或是NIL节点,所以在递归向上的过程中,每一步都保证下一步进行时,至少 X的子树是满足红黑特性的。因此子树的情况就可以认为是已经正确的了,这样,分析就只限制在X节点,X的父节点PX的兄弟节点W,以及W的两个子节点。这些个节点中。

W以及W的两个子节点C1C1的一共有五种组合,便有两种情况的处理是一致的,因此调整的过程可以分以下四个情况:

第一种情况:W是红色节点

红黑树的删除1

 

如上图,如果W是红色的,那么BD节点进行一次左旋,并把D(也就是原来的W)着为黑色,B节点(X的父节点)着为红色。然后让W指向X的新兄弟。这样,就把这种情况转化为了W为黑色的情况来解决。在这个变形中,这五个节点之间保持了红黑性质不变,而X指向的双黑色节点的位置和颜色特性都没有变化。变形后的情况如何解决呢?下面的都是W为黑色的问题,因此下面三种中总有一种会合适。

PS:有没有其它变形呢?有,比如CD进行右旋,B节点变为红色,变形后五个节点红黑正确的,但是这五个节点与树的其它部分相接处可能会产生问题,这样要考虑的因素就太多了。

 

第二种情况:W以及W的两个子节点都是黑色的

 

红黑树的删除2

 

如上图,注意,B即可以是红色也可以是黑色。

这种情况下,把D节点着成红色。然后把X的一个黑色推到父节点B中去,这时X就指向B节点了。变形前后,这五个节点间的黑高是没有变化的。

唯一可能产生问题的就是如果B原来是红色,那么BD两个红色相邻就破坏了第4个性质,这样新X的子树就有问题了。这本来不符合我们向上递归的假设。但正好在这种情况下递归就可以结束了。因为B节点原来是红色,现在双加一层黑色,那么X现在指向的这个节点就是红黑两色的,直接把X(也就是B)着为黑色。问题就已经完整解决了。

如果B节点现在是双层黑色,那就以B为新的X进行向上的下一次的递归。

 

第三种情况:W的左子节点是红色的且右子节点是黑色。

 

红黑树的删除3

 

  如上图,B即可以是黑色也可以是红色。

  把CD进行一次旋转,改变CD的颜色变形成新的结构。把问题转化成W的右子节点为红色的情况来解决。注意,原来C是红色的,所以C的子节点一定是黑色的,所以旋转中C节点的一个子树挂到之后着为红色的D节点上不会破坏红黑性质。变形后黑高度不变。

 

  第四种情况:W的右子节点是红色(左子节点可以是红色或黑色)

 

红黑树的删除4

 

  如上图,B节点可以是红色或是黑色。

  将BD进行一次左旋,并交换两者的颜色。再将E着为黑色。这时,只要将X的一层黑色脱去,整个问题也得到了解决。递归结束。(在代码上,为了标识递归结束,我们把X指向根节点)

 

  因此,只要按上面四种情况一直递归处理下去,X最终总会指向根结点或一个红色结点,这时我们就可以结束递归并把问题解决了。

  以上就是红黑色的节点删除过程。

 

 

  以下的简单的代码实现:

 

<code>

 

  1. // -------------------------------------------------------  
  2. // FileName : BinarySearchTree.cpp  
  3. // Date     : 2009-1-14   
  4. // Summary  : 红黑树的简单实现,节点中除了红黑树结构本身需要的信息之外,只  
  5. //            包含一个int域作为节点的key  
  6. // CopyLeft : 李诒雯  
  7. // -------------------------------------------------------  
  8.   
  9. #include <stdio.h>  
  10.   
  11. // 定义节点颜色  
  12. enum COLOR {  
  13.     BLACK = 0,  
  14.     RED  
  15. };  
  16.   
  17. // 红黑树节点  
  18. typedef struct tagRBTreeNode {  
  19.     int key;  
  20.     struct tagRBTreeNode *left;  
  21.     struct tagRBTreeNode *right;  
  22.     struct tagRBTreeNode *parent;  
  23.     unsigned char color;  
  24. }RBTreeNode, *PRBTreeNode;  
  25.   
  26. // 红黑树,包含一个指向根节点的指针  
  27. typedef struct tagRBTree {  
  28.     PRBTreeNode root;     
  29. }RBTree, *PRBTree;  
  30.   
  31. // 红黑树的NIL节点  
  32. static RBTreeNode NIL = {0, 0, 0, 0, BLACK};  
  33.   
  34. #define PNIL (&NIL)   // NIL节点地址  
  35.   
  36. // 生成一个红黑树节点,缺省的节点颜色是红黑。  
  37. PRBTreeNode CreateRBTreeNode(int keyVal)  
  38. {  
  39.     PRBTreeNode p = (PRBTreeNode)malloc(sizeof(RBTreeNode));  
  40.     p->color = RED;  
  41.     p->left = PNIL;  
  42.     p->right = PNIL;  
  43.     p->parent = PNIL;  
  44.     p->key = keyVal;  
  45.     return p;  
  46. }  
  47.   
  48. // 释放一个节点的内存  
  49. void DeleteRBTreeNode(PRBTreeNode pDel)  
  50. {  
  51.     if (PNIL != pDel) {  
  52.         free(pDel);  
  53.     }     
  54. }  
  55.   
  56. void InitRBTree(PRBTree pTree) // 初始化一棵红黑树  
  57. {  
  58.     pTree->root = PNIL;  
  59. }  
  60.   
  61. // 顺序遍历一棵红黑树,并对每个节点执行指定的操作  
  62. void INORDER_RBTREE_WALK(PRBTreeNode pRoot, void (*Action)(PRBTreeNode ))  
  63. {  
  64.     // 就是一个二叉树的中序遍历  
  65.     if (PNIL != pRoot) {  
  66.         INORDER_RBTREE_WALK(pRoot->left, Action);  
  67.         Action(pRoot);  
  68.         INORDER_RBTREE_WALK(pRoot->right, Action);  
  69.     }  
  70. }  
  71.   
  72. // 查找指定键值的节点  
  73. PRBTreeNode RBTREE_SEARCH(PRBTreeNode pRoot, int val_key)  
  74. {  
  75.     while ((PNIL != pRoot) && (val_key != pRoot->key)) {  
  76.         pRoot = (val_key < pRoot->key ? pRoot->left : pRoot->right);      
  77.     }  
  78.     return pRoot;  
  79. }  
  80.   
  81. // 查找最大键值节点  
  82. PRBTreeNode RBTREE_MAX(PRBTreeNode pRoot)  
  83. {  
  84.     while (PNIL != pRoot->right) {  
  85.         pRoot = pRoot->right;     
  86.     }  
  87.     return pRoot;  
  88. }  
  89.   
  90. // 查找最小键值节点  
  91. PRBTreeNode RBTREE_MIN(PRBTreeNode pRoot)  
  92. {  
  93.     while (PNIL != pRoot->left) {  
  94.         pRoot = pRoot->left;      
  95.     }  
  96.     return pRoot;  
  97. }  
  98.   
  99. // 查找指定节点的后继节点  
  100. PRBTreeNode RBTREE_SUCCESSOR(PRBTreeNode pRoot)  
  101. {  
  102.     if (PNIL != pRoot->right) {  
  103.         return RBTREE_MIN(pRoot->right);  
  104.     }  
  105.     PRBTreeNode pParent = pRoot->parent;  
  106.     while((PNIL != pParent) && (pRoot == pParent->right)) {  
  107.         pRoot = pParent;  
  108.         pParent = pRoot->parent;              
  109.     }   
  110.     return pParent;  
  111. }  
  112.   
  113. // 查找指定节点的前趋节点  
  114. PRBTreeNode RBTREE_PREDECESSOR(PRBTreeNode pRoot)  
  115. {  
  116.     if (PNIL != pRoot->left) {  
  117.         return RBTREE_MAX(pRoot->left);  
  118.     }  
  119.     PRBTreeNode pParent = pRoot->parent;  
  120.     while((PNIL != pParent) && (pRoot == pRoot->left)) {  
  121.         pRoot = pParent;  
  122.         pParent = pRoot->parent;              
  123.     }   
  124.     return pParent;  
  125. }  
  126.   
  127. // 对指定节点进行左旋  
  128. static void LEFT_ROTATION(PRBTree pTree, PRBTreeNode pNode)  
  129. {  
  130.     PRBTreeNode pRight = pNode->right;  
  131.     pRight->parent = pNode->parent;  
  132.     if(pNode->parent->left == pNode){  
  133.         pRight->parent->left = pRight;  
  134.     }  
  135.     else {  
  136.         pRight->parent->right = pRight;  
  137.     }  
  138.   
  139.     if (PNIL == pRight->parent) {  
  140.         pTree->root = pRight;  
  141.     }  
  142.     if (PNIL != pRight->left) {  
  143.         pRight->left->parent = pNode;  
  144.     }  
  145.     pNode->right = pRight->left;  
  146.     pNode->parent = pRight;  
  147.     pRight->left = pNode;  
  148. }  
  149.   
  150. // 对指定节点进行右旋  
  151. static void RIGHT_ROTATION(PRBTree pTree, PRBTreeNode pNode)  
  152. {  
  153.     PRBTreeNode pLeft = pNode->left;  
  154.     pLeft->parent = pNode->parent;  
  155.     if(pNode->parent->left == pNode){  
  156.         pLeft->parent->left = pLeft;  
  157.     }  
  158.     else {  
  159.         pLeft->parent->right = pLeft;  
  160.     }  
  161.   
  162.     if (PNIL == pLeft->parent) {  
  163.         pTree->root = pLeft;  
  164.     }  
  165.     if (PNIL != pLeft->right) {  
  166.         pLeft->right->parent = pNode;  
  167.     }     
  168.     pNode->left = pLeft->right;  
  169.     pNode->parent = pLeft;  
  170.     pLeft->right = pNode;  
  171. }  
  172.   
  173. // 在红黑树插入动作后进行红黑性质恢复  
  174. static void FIX_UP_RB_AFTER_INSERT(PRBTree pTree, PRBTreeNode pNode)  
  175. {  
  176.     while(RED == pNode->parent->color) {  
  177.         if (pNode->parent == pNode->parent->parent->left){  
  178.             PRBTreeNode pUncleNode = pNode->parent->parent->right;  
  179.             if (RED == pUncleNode->color){  
  180.                 pNode->parent->color = BLACK;  
  181.                 pUncleNode->color = BLACK;  
  182.                 pNode = pUncleNode->parent;  
  183.                 pNode->color = RED;  
  184.             }  
  185.             else   
  186.             {  
  187.                 if (pNode == pNode->parent->right) {  
  188.                     pNode = pNode->parent;  
  189.                     LEFT_ROTATION(pTree, pNode);  
  190.                 }  
  191.                 pNode->parent->color = BLACK;  
  192.                 PRBTreeNode TempP = pNode->parent->parent;  
  193.                 TempP->color = RED;  
  194.                 RIGHT_ROTATION(pTree, TempP);  
  195.             }  
  196.         }  
  197.         else{  
  198.             PRBTreeNode pUncleNode = pNode->parent->parent->left;  
  199.             if (RED == pUncleNode->color){  
  200.                 pNode->parent->color = BLACK;  
  201.                 pUncleNode->color = BLACK;  
  202.                 pNode = pUncleNode->parent;  
  203.                 pNode->color = RED;  
  204.             }  
  205.             else   
  206.             {  
  207.                 if (pNode == pNode->parent->left) {  
  208.                     pNode = pNode->parent;  
  209.                     RIGHT_ROTATION(pTree, pNode);  
  210.                 }  
  211.                 pNode->parent->color = BLACK;  
  212.                 PRBTreeNode TempP = pNode->parent->parent;  
  213.                 TempP->color = RED;  
  214.                 LEFT_ROTATION(pTree, TempP);  
  215.             }  
  216.         }  
  217.     }  
  218.     pTree->root->color = BLACK;  
  219. }  
  220.   
  221. // 红黑树的节点插入  
  222. void RBTREE_INSERT(PRBTree pTree, PRBTreeNode pNode)  
  223. {  
  224.     PRBTreeNode pNodePosition = pTree->root;  
  225.     PRBTreeNode pParent = PNIL;  
  226.   
  227.     while (PNIL != pNodePosition) {  
  228.         pParent = pNodePosition;  
  229.         pNodePosition = (pNode->key > pNodePosition->key ?   
  230.             pNodePosition->right : pNodePosition->left);  
  231.     }  
  232.       
  233.     pNode->parent = pParent;  
  234.     if (PNIL == pParent) {  
  235.         pTree->root = pNode;          
  236.     }  
  237.     else {  
  238.         if (pNode->key > pParent->key) {  
  239.             pParent->right = pNode;  
  240.         }  
  241.         else {  
  242.             pParent->left = pNode;  
  243.         }  
  244.     }  
  245.     FIX_UP_RB_AFTER_INSERT(pTree, pNode);  
  246. }  
  247.   
  248. // 在红黑树删除动作后进行红黑性质恢复  
  249. static void FIX_UP_RB_AFTER_DELETE(PRBTree pTree, PRBTreeNode pNode)  
  250. {  
  251.     while ((pNode->color == BLACK) && (pNode != pTree->root)) {  
  252.         if (pNode == pNode->parent->left){  
  253.             PRBTreeNode pBrother = pNode->parent->right;  
  254.             if (RED == pBrother->color) {  
  255.                 pBrother->color = BLACK;  
  256.                 pNode->parent->color = RED;  
  257.                 LEFT_ROTATION(pTree, pNode->parent);  
  258.                 pBrother = pNode->parent->right;  
  259.             }  
  260.             if ((BLACK == pBrother->right->color) && (BLACK == pBrother->left->color)) {  
  261.                 pBrother->color = RED;  
  262.                 pNode = pNode->parent;  
  263.             }  
  264.             else {  
  265.                 if (BLACK == pBrother->right->color) {  
  266.                     pBrother->color = RED;  
  267.                     pBrother->left->color = BLACK;  
  268.                     RIGHT_ROTATION(pTree, pBrother);  
  269.                     pBrother = pNode->parent->right;  
  270.                 }  
  271.                 pBrother->right->color = BLACK;  
  272.                 pBrother->color = pNode->parent->color;               
  273.                 pNode->parent->color = BLACK;  
  274.                 LEFT_ROTATION(pTree, pNode->parent);  
  275.                 pNode = pTree->root;  
  276.             }  
  277.         }  
  278.         else{  
  279.             PRBTreeNode pBrother = pNode->parent->left;  
  280.             if (RED == pBrother->color) {  
  281.                 pBrother->color = BLACK;  
  282.                 pNode->parent->color = RED;  
  283.                 RIGHT_ROTATION(pTree, pNode->parent);  
  284.                 pBrother = pNode->parent->left;  
  285.             }  
  286.             if ((BLACK == pBrother->left->color) && (BLACK == pBrother->right->color)) {  
  287.                 pBrother->color = RED;  
  288.                 pNode = pNode->parent;  
  289.             }  
  290.             else {  
  291.                 if (BLACK == pBrother->left->color) {  
  292.                     pBrother->color = RED;  
  293.                     pBrother->right->color = BLACK;  
  294.                     LEFT_ROTATION(pTree, pBrother);  
  295.                     pBrother = pNode->parent->left;  
  296.                 }  
  297.                 pBrother->left->color = BLACK;  
  298.                 pBrother->color = pNode->parent->color;               
  299.                 pNode->parent->color = BLACK;  
  300.                 RIGHT_ROTATION(pTree, pNode->parent);  
  301.                 pNode = pTree->root;  
  302.             }  
  303.         }  
  304.     }  
  305.     pNode->color = BLACK;  
  306. }  
  307.   
  308. // 红黑树的节点删除  
  309. PRBTreeNode RBTREE_DELETE(PRBTree pTree, PRBTreeNode pDel)  
  310. {  
  311.     PRBTreeNode pRelDel;  
  312.     if ((PNIL == pDel->left) || (PNIL == pDel->right)) {  
  313.         pRelDel = pDel;  
  314.     }  
  315.     else { //  
  316.         pRelDel = RBTREE_SUCCESSOR(pDel);  
  317.     }  
  318.   
  319.     PRBTreeNode pChildOfDel;  
  320.     pChildOfDel = (pRelDel->left!= PNIL ? pRelDel->left : pRelDel->right);  
  321.   
  322.     //  
  323.     pChildOfDel->parent = pRelDel->parent;  
  324.       
  325.     if (PNIL == pRelDel->parent) {  
  326.         pTree->root = pChildOfDel;  
  327.     }  
  328.     else {  
  329.         if (pRelDel == pRelDel->parent->left){  
  330.             pRelDel->parent->left = pChildOfDel;  
  331.         }  
  332.         else {  
  333.             pRelDel->parent->right = pChildOfDel;  
  334.         }  
  335.     }  
  336.   
  337.     if (pRelDel != pDel) {  
  338.         pDel->key = pRelDel->key;  
  339.     }  
  340.   
  341.     if (pRelDel->color == BLACK) {  
  342.         FIX_UP_RB_AFTER_DELETE(pTree, pChildOfDel);  
  343.     }  
  344.     return pRelDel;  
  345. }  
  346.   
  347. /*=============================================*/  
  348. // 测试用函数,打印节点键值。可以传给遍历函数作为第二个参数  
  349. void PrintNode(PRBTreeNode p)  
  350. {  
  351.     if (NULL != p) {  
  352.         printf("%2d ", p->key);  
  353.     }  
  354.     else {  
  355.         printf("NULL!");  
  356.     }  
  357. }  
  358.   
  359. // 打印出红黑树每个节点的各项值。  
  360. void RBTREE_STRUCTURE(PRBTreeNode pRoot)  
  361. {  
  362. #define GetKey(p) (p==PNIL?-1:p->key)  
  363.     //  
  364.     if (PNIL != pRoot) {  
  365.         printf("KeyValue = %d, color = %s, Left = %d, Right = %d, Parent = %d/n",  
  366.             pRoot->key, pRoot->color==BLACK?"BLACK":"RED", GetKey(pRoot->left),   
  367.             GetKey(pRoot->right), GetKey(pRoot->parent));  
  368.         RBTREE_STRUCTURE(pRoot->left);  
  369.         RBTREE_STRUCTURE(pRoot->right);  
  370.     }  
  371. }  
  372.   
  373. /*=============================================*/  
  374. int _tmain(int argc, _TCHAR* argv[])  
  375. {  
  376.     RBTree bsTree;  
  377.     InitRBTree(&bsTree);  
  378.   
  379. #define TEST_NUM_COUNT (10)  
  380.     int values[TEST_NUM_COUNT];  
  381.   
  382.     for (int i=0; i<TEST_NUM_COUNT; ++i) {  
  383.         values[i] = rand()%(TEST_NUM_COUNT*10);  
  384.         PRBTreeNode p = CreateRBTreeNode(values[i]);  
  385.         RBTREE_INSERT(&bsTree, p);  
  386.       
  387.           
  388.         printf("After Insert %2d:  ", values[i]);  
  389.         INORDER_RBTREE_WALK(bsTree.root, PrintNode);      
  390.         printf("RB-Tree Nodes Information/n");  
  391.           
  392.         RBTREE_STRUCTURE(bsTree.root);  
  393.         printf("-------------------------------/n");  
  394.     }  
  395.   
  396.     printf("###############################/n");  
  397.     printf("===============================/n");  
  398.   
  399.     for (int i=0; i<TEST_NUM_COUNT; ++i) {  
  400.         PRBTreeNode pDel = RBTREE_DELETE(&bsTree, RBTREE_SEARCH(bsTree.root, values[i]));  
  401.         DeleteRBTreeNode(pDel);  
  402.         printf("After Delete %2d:  ", values[i]);  
  403.         INORDER_RBTREE_WALK(bsTree.root, PrintNode);  
  404.         printf("RB-Tree Nodes Information/n");  
  405.         RBTREE_STRUCTURE(bsTree.root);  
  406.         printf("-------------------------------/n");  
  407.           
  408.     }  
  409.   
  410.     return 0;  
  411. }  

 

</code>

 

 

最后还可以参考下:

http://www.cppblog.com/converse/archive/2007/11/28/37430.html

还有一个叫”size balanced tree“可以google下

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值