首页 > 代码库 > 红黑树

红黑树

性质导致了 强约束,也导致了O(lgn)的高度
 
性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点(不包括该节点)到其每个叶子的所有简单路径都包含相同数目的黑色节点。
 
得出的结论
1 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长
2 最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点
3 红色结点的父结点或子节点一定是黑色结点
4 在五个性质前提下推导出树的高度为o(lgn)的结论,
   即进行插入或删除时,只需关注保持五个性质,而五个性质决定了算法的复杂度为o(lgn)
 
插入需要注意的点

1 插入新节点总是红色节点

2 如果插入节点的父节点是黑色, 能维持性质

3 如果插入节点的父节点是红色, 破坏了性质. 故需要通过重新着色或旋转, 来维持性质

插入关键部分

解决相邻的两个节点为红色的结点,同时维持任意路径黑高度(黑色结点个数)相同

删除需要需要注意的点

1 如果删除的是红色节点, 不破坏性质

2 如果删除的是黑色节点, 那么这个路径上就会少一个黑色节点, 破坏了性质. 故需要通过重新着色或旋转, 来维持性质

删除关键部分

如果删除的是左子树黑色结点,维持的最终目的是左右黑高度相同,即维持右子树黑高度的同时,增加左子树的黑高度

 

代码主要根据上图实现 

  1 #include <iostream>
  2 #include <crtdbg.h>
  3 #include <string>
  4 using namespace std;
  5 /*红黑树*/
  6 /*实现中假设关键元素互不相同*/
  7 typedef int DataType;
  8 
  9 class BST
 10 {
 11 private:
 12     enum {BLACK = 0, RED = 1};
 13     /*结点的数据结构*/
 14     struct node
 15     {
 16         DataType data;
 17         bool color;
 18         node *left;
 19         node *right;
 20         node *parent;
 21 
 22         node()
 23         {
 24             color = RED;
 25             left = NULL;
 26             right = NULL;
 27             parent = NULL;
 28             data = http://www.mamicode.com/0;
 29         }
 30         node *Grandfather()
 31         {
 32             if (parent == NULL)
 33             {
 34                 return NULL;
 35             }
 36             return parent->parent;
 37         }
 38         node *Uncle()
 39         {
 40             if(Grandfather() == NULL)
 41                 return NULL;
 42             if (parent == Grandfather()->left)
 43             {
 44                 return Grandfather()->right;
 45             }
 46             else
 47             {
 48                 return Grandfather()->left;
 49             }
 50         }
 51         node *Sibling()
 52         {
 53             if (parent->left == this)
 54             {
 55                 return parent->right;
 56             }
 57             else
 58             {
 59                 return parent->left;
 60             }
 61         }
 62     };
 63     void Left_rotate(node *p )
 64     {
 65         //把y的左子树连接到p的右子树下面,并更新父节点
 66         node *y = p->right;
 67         p->right = y->left;
 68         if (y->left != NIL)
 69         {
 70             y->left->parent = p;
 71         }
 72         //更新y的父节点
 73         y->parent = p->parent;
 74         if (p->parent == NIL) //判断根结点
 75         {
 76             root = y;
 77         }
 78         //更新原x父节点的子节点
 79         else if (p == p->parent->left)
 80         {
 81             p->parent->left = y;
 82         }
 83         else
 84         {
 85             p->parent->right = y;
 86         }
 87         //更新x 与 y 的关系
 88         y->left = p;
 89         p->parent = y;
 90     }
 91     void Right_rotate(node *p)
 92     {
 93         node *y = p->left;
 94         p->left = y->right;
 95         if (y->right != NIL)
 96         {
 97             y->right->parent = p;
 98         }
 99         y->parent = p->parent;
100         if (p->parent == NIL) //判断根结点
101         {
102             root = y;
103         }
104         else if (p == p->parent->left)
105         {
106             p->parent->left = y;
107         }
108         else
109         {
110            p->parent->right = y;
111         }
112         y->right = p;
113         p->parent = y;
114     }
115     string OutputColor(bool color)
116     {
117         return color ? "RED":"BLACK";
118     }
119     /*纠正因插入而破坏的性质*/
120     void Insert_Fixup(node *p)
121     {
122         /*由于p结点为红色(新插入默认赋值为红色),
123           判断p的父节点是否为红色,如果为红色则破坏了红黑树的性质,需要维护*/
124         while(p->parent->color == RED)
125         {
126             if (p->parent == p->Grandfather()->left) 
127             {
128                 node *y = p->Grandfather()->right;
129                 if (y->color == RED)  /*case 3*/
130                 {
131                     p->parent->color = BLACK;
132                     y->color = BLACK;
133                     p->Grandfather()->color = RED;
134                     p = p->Grandfather();/*p结点向上移*/
135                 }
136                 else if (p == p->parent->right) /*case 2*/
137                 {
138                     p = p->parent;/*p结点向上移*/
139                     Left_rotate(p);
140                 }
141                 else
142                 {
143                     p->parent->color = BLACK; /*case 3*/
144                     p->Grandfather()->color = RED;
145                     Right_rotate(p->Grandfather());/*注意是祖父结点*/
146                 }
147             }
148             else
149             {
150                 node *y = p->Grandfather()->left;
151                 if (y->color == RED)  /*case 3*/
152                 {
153                     p->parent->color = BLACK;
154                     y->color = BLACK;
155                     p->Grandfather()->color = RED;
156                     p = p->Grandfather();
157                 }
158                 else if (p == p->parent->left) /*case 2*/
159                 {
160                     p = p->parent;
161                     Right_rotate(p);
162                 }
163                 else
164                 {
165                     p->parent->color = BLACK; /*case 3*/
166                     p->Grandfather()->color = RED;
167                     Left_rotate(p->Grandfather());
168                 }
169             }
170         }
171         root->color = BLACK;/*确保插入根结点时,满足红黑树的性质*/
172     }
173     /*纠正因删除而破坏的性质*/
174     void Delete_Fixup(node *p)
175     {
176         /*判断p结点是否为黑色
177          如果是红色不破坏红黑树性质
178          原因1.删除红色树黑高度不变2.不存在两个相邻红色结点
179          3. 如果y是红色的,就不可能是根,即根仍然是黑色的
180          为保证性质任何路径上黑结点个数相同,假设p结点为多重颜色(双黑或红黑)*/
181         while (p != root && p->color == BLACK)
182         {
183             if(p == p->parent->left)
184             {
185                 node *pSibling = p->parent->right;
186                 if (pSibling->color == RED)/*case1*/
187                 {
188                     pSibling->color = BLACK;
189                     Left_rotate(p->parent);
190                     pSibling = p->parent->right;
191                 }
192                 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/
193                 {
194                     pSibling->color = RED;
195                     p = p->parent;
196                 }                
197                 else
198                 {
199                     if (pSibling->right->color == BLACK)/*case3*/
200                     {
201                         pSibling->left->color = BLACK;
202                         pSibling->color = RED;
203                         Right_rotate(pSibling);
204                         pSibling = p->parent->right;
205                     }
206                     pSibling->color = p->parent->color;/*case4*/
207                     p->parent->color = BLACK;
208                     pSibling->right->color = BLACK;
209                     Left_rotate(p->parent);
210                     p = root;
211                 }
212             }
213             else
214             {
215                 node *pSibling = p->parent->left;
216                 if (pSibling->color == RED)/*case1*/
217                 {
218                     pSibling->color = BLACK;
219                     Left_rotate(p->parent);
220                     pSibling = p->parent->left;
221                 }
222                 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/
223                 {
224                     pSibling->color = RED;
225                     p = p->parent;
226                 }                
227                 else
228                 {
229                     if (pSibling->left->color == BLACK)/*case3*/
230                     {
231                         pSibling->right->color = BLACK;
232                         pSibling->color = RED;
233                         Left_rotate(pSibling);
234                         pSibling = p->parent->left;
235                     }
236                     pSibling->color = p->parent->color;/*case4*/
237                     p->parent->color = BLACK;
238                     pSibling->right->color = BLACK;
239                     Right_rotate(p->parent);
240                     p = root;
241                 }
242             }
243         }
244         p->color = BLACK;
245     }
246     /*中序遍历*/
247     void InOrderTree(node *p)
248     {
249         if (p == NULL || p == NIL)
250         {
251             return;
252         }
253         InOrderTree(p->left);
254         cout << p->data << "\t" << OutputColor(p->color) << endl;
255         InOrderTree(p->right);
256     }
257     /*获取结点的后继*/
258     node *TreeAfter(node *p)
259     {
260         if (p->right != NIL)
261         {
262             node *pTemp = p->right;
263             while(pTemp != NIL)
264             {
265                 p = pTemp;
266                 pTemp = p->left;
267             }
268         }
269         return p;
270     }
271 private:
272     node *root;
273     node *NIL;
274 public:
275     BST()
276     {
277         NIL = new node();
278         NIL->color = BLACK;
279         root = NULL;
280     }
281     ~BST()
282     {
283         if (root != NULL)
284         {
285             Destory(root);
286             root = NULL;
287         }
288         delete NIL;
289         NIL = NULL;
290     }
291     void Destory(node *p)
292     {
293         if (p == NULL || p == NIL)
294             return;
295         Destory(p->left);
296         Destory(p->right);
297         delete p;
298     }
299     void Insert(DataType data)
300     {
301         node *p = root;
302         node *pTemp = NIL;
303         while( p != NIL && p != NULL)
304         {
305             pTemp = p;
306             if (data < p->data)
307             {
308                 p = p->left;
309             }
310             else
311             {
312                 p = p->right;
313             }
314         }
315         node *pNew = new node();
316         pNew->parent = pTemp;
317         pNew->data =http://www.mamicode.com/ data;
318         if (pTemp == NIL)
319         {
320             root = pNew;
321         }
322         else
323         {
324             if (pNew->data < pTemp->data)
325             {
326                 pTemp->left = pNew;
327             }
328             else
329             {
330                 pTemp->right = pNew;
331             }
332         }
333         pNew->left = NIL;
334         pNew->right = NIL;
335         Insert_Fixup(pNew);
336     }
337     /*非递归版本*/
338     node* Find(DataType key)
339     {
340         node *p = root;
341         while(p != NULL && p->data != key)
342         {
343             if (key < p->data)
344             {
345                 p = p->left;
346             }
347             else
348             {
349                 p = p->right;
350             }
351         }
352         return p;
353     }
354     void Delete(DataType data)
355     {
356         /*获取data的指针*/
357         node *p = Find(data);
358         node *pDelete= NIL;
359         node *pNode = NIL;/*要删除节点的子节点*/
360         if (p->left == NIL || p->right == NIL)
361         {
362             pDelete = p;
363         }
364         else
365         {
366             pDelete = TreeAfter(p);
367         }
368         /*获取子结点*/
369         if(pDelete->left != NIL)
370         {
371             pNode = pDelete->left;
372         }
373         else
374         {
375             pNode = pDelete->right;
376         }
377         /*更新父结点*/
378         pNode->parent = pDelete->parent;
379         /*更新子结点*/
380         if (pDelete->parent == NIL)
381         {
382             root = pNode;
383         }
384         else if(pDelete->parent->left == pDelete)
385         {
386             pDelete->parent->left = pNode;
387         }
388         else
389         {
390             pDelete->parent->right = pNode;
391         }
392         if (pDelete != p)
393         {
394             p->data = http://www.mamicode.com/pDelete->data;
395         }
396         /*如果要删除的结点pDelete是红色的,
397         不影响黑高度,即不会破坏红黑树的性质*/
398         if (pDelete->color == BLACK)
399         {
400             Delete_Fixup(pNode);
401         }

402         delete pDelete;
403         pDelete = NULL;
404     }
405     void InOrder()
406     {
407         if (root == NULL)
408         {
409             return;
410         }
411         InOrderTree(root);
412         cout << endl;
413     }
414 };
415 
416 void main()
417 {
418     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
419 
420      BST bst;
421      
422      bst.Insert(11);
423      bst.Insert(2);
424      bst.Insert(14);
425      bst.Insert(15);
426      bst.Insert(1);
427      bst.Insert(7);
428      bst.Insert(5);
429      bst.Insert(8);
430      bst.Insert(4);
431 
432      bst.InOrder();
433 
434      //bst.Delete(4);
435      //bst.Delete(14);
436      bst.Delete(7);
437      bst.InOrder();
438 
439     system("pause");
440 }

 (转载请注明作者和出处 :)  Seven++ http://www.cnblogs.com/sevenPP/  )