紅黑樹學習

最近在研究map和unordered_map,接觸到了紅黑樹這個東西..大學一直想學而始終沒學,因此學習學習 感謝做者
html

1,http://blog.csdn.net/v_JULY_v/article/details/6105630node

2,http://blog.csdn.net/v_JULY_v/article/details/6109153算法

3,http://blog.csdn.net/v_JULY_v/archive/2011/01/03/6114226.aspx學習

4,http://blog.csdn.net/v_JULY_v/archive/2011/01/09/6124989.aspxspa

5,http://blog.csdn.net/v_JULY_v/article/details/6284050.net

6,http://blog.csdn.net/v_JULY_v/article/details/6285620指針

1、紅黑樹的介紹

紅黑樹是一種二叉查找樹,但在每一個結點上增長一個存儲位表示結點的顏色,能夠是Red或Black。經過對任何一條從根到葉子的路徑上各個結點着色方式的限制,紅黑樹確保沒有一條路徑會比其餘路徑長出倆倍,於是是接近平衡的code

紅黑樹,做爲一棵二叉查找樹,知足二叉查找樹的通常性質。下面,來了解下 二叉查找樹的通常性質。htm

二叉查找樹

二叉查找樹,也稱有序二叉樹(ordered binary tree),或已排序二叉樹(sorted binary tree),是指一棵空樹或者具備下列性質的二叉樹:blog

  • 若任意節點的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值
  • 若任意節點的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值
  • 任意節點的左、右子樹也分別爲二叉查找樹。
  • 沒有鍵值相等的節點(no duplicate nodes)

由於一棵由n個結點隨機構造的二叉查找樹的高度爲log2n,因此瓜熟蒂落,二叉查找樹的通常操做的執行時間爲O(log2n)。但二叉查找樹若退化成了一棵具備n個結點的線性鏈後,則這些操做最壞狀況運行時間爲O(n)。(當二叉查找樹是平衡二叉查找樹[AVL]的時候時間複雜度是O(log2n),而斜樹的時候是O(n)

二叉平衡樹: 它是一 棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,而且左右兩個子樹都是一棵平衡二叉樹。構造與調整方法 平衡二叉樹的經常使用算法有紅黑樹、AVL、Treap等。 

 

紅黑樹雖然本質上是一棵二叉查找樹,但它在二叉查找樹的基礎上增長了着色和相關的性質使得紅黑樹相對平衡,從而保證了紅黑樹的查找、插入、刪除的時間複雜度最壞爲O(log n)

但它是如何保證一棵n個結點的紅黑樹的高度始終保持在logn的呢?這就引出了紅黑樹的5個性質:

  1. 每一個結點要麼是紅的要麼是黑的。  
  2. 根結點是黑的。  
  3. 每一個葉結點(葉結點即指樹尾端NIL指針或NULL結點)都是黑的。  
  4. 若是一個結點是紅的,那麼它的兩個兒子都是黑的。  
  5.  對於任意結點而言,其到葉結點樹尾端NIL指針的每條路徑都包含相同數目的黑結點。 

正是紅黑樹的這5條性質,使一棵n個結點的紅黑樹始終保持了logn的高度,從而也就解釋了上面所說的「紅黑樹的查找、插入、刪除的時間複雜度最壞爲O(log n)」這一結論成立的緣由。

 

(注:上述第三、5點性質中所說的NULL結點,包括wikipedia.算法導論上所認爲的葉子結點即爲樹尾端的NIL指針,或者說NULL結點。然百度百科以及網上一些其它博文直接說的葉結點,則易引發誤會,因,此葉結點非子結點)

以下圖所示,便是一顆紅黑樹(下圖引自wikipedia:http://t.cn/hgvH1l):

此圖忽略了葉子和根部的父結點。同時,上文中咱們所說的 "葉結點" 或"NULL結點",如上圖所示,它不包含數據而只充當樹在此結束的指示,這些節點在繪圖中常常被省略,望看到此文後的讀者朋友注意。(上圖 NIL是NULL也就是最後的葉節點只不過這個是實現爲NULL值,仍是一個假節點,看你喜歡了)

2、樹的旋轉知識

    當在對紅黑樹進行插入和刪除等操做時,對樹作了修改可能會破壞紅黑樹的性質。爲了繼續保持紅黑樹的性質,能夠經過對結點進行從新着色,以及對樹進行相關的旋轉操做,即經過修改樹中某些結點的顏色及指針結構,來達到對紅黑樹進行插入或刪除結點等操做後繼續保持它的性質或平衡的目的。

    樹的旋轉分爲左旋和右旋,下面藉助圖來介紹一下左旋和右旋這兩種操做。

1.左旋

 

如上圖所示,當在某個結點pivot上,作左旋操做時,咱們假設它的右孩子y不是NIL[T],pivot能夠爲任何不是NIL[T]的左子結點。左旋以pivot到Y之間的鏈爲「支軸」進行,它使Y成爲該子樹的新根,而Y的左孩子b則成爲pivot的右孩子

 1 LeftRoate(T, pivot)
 2 y <- pivot.right                  //定義y: y是x的右孩子
 3 pivot.right <- y.left              //y的左孩子成爲x的右孩子
 4 
 5 if y.left ≠ T.nil
 6     y.left.paret <- pivot
 7 y.paret <- x.paret                   //x的父節點成爲y的父節點
 8 if pivot.paret = T.nil
 9     then T.root <-- y
10 else if pivot = pivot.paret.left
11     then pivot.paret.right <-- y
12 else pivot.paret.right <-- y
13 y.left <-- pivot                //x做爲y的左孩子
14 pivot.paret <-- y

2.右旋    右旋與左旋差很少,再次不作詳細介紹

 

 樹在通過左旋右旋以後,樹的搜索性質保持不變,但樹的紅黑性質則被破壞了,因此,紅黑樹插入和刪除數據後,須要利用旋轉與顏色重塗來從新恢復樹的紅黑性質。

 

3、紅黑樹的插入

要真正理解紅黑樹的插入,還得先理解二叉查找樹的插入。磨刀不誤砍柴工,我們再來了解一下二叉查找樹的插入和紅黑樹的插入。

若是要在二叉查找樹中插入一個結點,首先要查找到結點要插入的位置,而後進行插入。假設插入的結點爲z的話,插入的僞代碼以下:

 

 1 TREE-INSERT(T, z)
 2 y  ← NIL
 3 x  ←T.root
 4 while x ≠ NIL
 5     do y  ← x
 6     if z.key < x.key
 7         then x  ← x.left
 8     else x  ← x.right
 9 z.p  ← y
10 if y == NIL
11     then T.root  ← z
12 else if z.key < y.key
13     then y.left  ← z
14 else y.right  ← z
相關文章
相關標籤/搜索