紅黑樹

性質致使了 強約束,也致使了O(lgn)的高度
 
性質1. 節點是紅色或黑色。

性質2. 根是黑色。node

性質3. 全部葉子都是黑色(葉子是NIL節點)。ios

性質4. 每一個紅色節點的兩個子節點都是黑色。(從每一個葉子到根的全部路徑上不能有兩個連續的紅色節點)算法

性質5. 從任一節點(不包括該節點)到其每一個葉子的全部簡單路徑都包含相同數目的黑色節點。
 
得出的結論
1 從根到葉子的最長的可能路徑很少於最短的可能路徑的兩倍長
2 最短的可能路徑都是黑色節點,最長的可能路徑有交替的紅色和黑色節點
3 紅色結點的父結點或子節點必定是黑色結點
4 在五個性質前提下推導出樹的高度爲o(lgn)的結論,
   即進行插入或刪除時,只需關注保持五個性質,而五個性質決定了算法的複雜度爲o(lgn)
 
插入須要注意的點

1 插入新節點老是紅色節點數據結構

2 若是插入節點的父節點是黑色, 能維持性質this

3 若是插入節點的父節點是紅色, 破壞了性質. 故須要經過從新着色或旋轉, 來維持性質spa

插入關鍵部分指針

解決相鄰的兩個節點爲紅色的結點,同時維持任意路徑黑高度(黑色結點個數)相同code

刪除須要須要注意的點blog

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 = 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 = 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 = 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/  )

相關文章
相關標籤/搜索