演算法導論例程 紅黑樹

2021-07-09 22:08:24 字數 2895 閱讀 7478

紅黑樹是比較重要的資料結構,作為乙個典型的平衡二叉樹(沒有一條簡單路徑是其他路徑的二倍)。它與二叉搜尋樹的區別是它的結點多了乙個屬性——color,color有兩種值,red和black,顏色的選取遵循以下原則:

1)每個節點是紅色的,或是黑色的;

2)根節點是黑色的;(鬆弛紅黑樹 relaxed red-black tree的根節點可以是紅色)

3)每個葉節點(nil)是黑色的;

4)如果乙個節點是紅色的,那麼他的兩個子節點都是黑色的;

5)對每個節點,從該節點到其所有後代節點的簡單路徑上,均包含相同數目的黑色節點;

#define black 0;

#define red 1;

using namespace std;

typedef struct red_black_tree

rbt;

可見性質中有很多都是用黑節點來定義的,所以為了描述方便還引進了乙個概念——黑高bh(x),指的是從節點x到葉節點的任一簡單路徑的黑節點的數目。

由此可以推得,以x為根的子樹至少包含2^(bh(x)) - 1個內部節點,推廣到整棵樹,得到有n個節點的紅黑樹其高度不超過2lg(n+1)。

搜尋樹的操作insert和delete在紅黑樹上的最壞執行時間為o(lgn),由於這兩種操作對樹的結構做出了改變,我們需要乙個機制來維護紅黑樹的性質,由於紅黑樹是有color屬性的,所以簡單的trans操作不適用,我們引進新的基本操作——旋轉。

紅黑樹的旋轉分為左旋和右旋,以左旋為例:對節點x的左旋,假設x有右孩子y,那麼旋轉之後x成為y的左孩子,y的左孩子成為x的右孩子,y代替了x的位置。這樣做不會改變二叉搜尋樹的性質。

要提示一點的是,紅黑樹中不允許出現「沒有顏色」的空節點,因此本節**中所有的null都應替換為以下宣告的乙個nil哨兵節點,它是一種啞元節點,對速度沒有什麼影響。

rbt nil;

void left_rotate(rbt* root, rbt* key)

else if (key == key->p->left)

key->p->left = key_r;

else

key->p->right = key_r;

key_r->p = key->p;

key_r->left = key;

key->p = key_r;

}

void rigth_rotate(rbt* root, rbt* key)

else if (key == key->p->left)

key->p->left = key_l;

else

key->p->right = key_l;

key_l->p = key->p;

key_l->right = key;

key->p = key_l;

}

有了左旋和右旋作為基礎,我們就可以考慮對紅紅黑樹的插入操作了。首先我們要明確的一點是——紅黑樹依然是二叉搜尋樹,因此我們可以仿照二叉搜尋樹的插入方法來寫出 紅黑樹的插入,這樣可以保證我們的插入操作不會使樹違反二叉搜尋樹的性質。

void rb_insert(rbt* root, rbt* key)

key->p = y;

if (y == null)

root = key;

else if (key->num < y->num)

y->left = key;

else

y->right = key;

key->left = null;

key->right = null;

key->color = red;

rb_insert_fix(root, key);

}

唯一的不同就是我們把新插入的節點著色為紅色,之所以著為紅色是因為這樣只會使它違反紅黑樹的性質2和性質4,方便我們後期的維護。

接下來呢我們討論關鍵字節點的父節點、祖父節點和叔叔節點的顏色對其進行討論,其中case2和case3是具有關聯性的,case2完成旋轉之後一定會成為case3。具體的討論參見書,這裡就不畫圖了。

case1: key的叔叔節點是紅色

case2:key的叔叔節點是黑色的且key是乙個右孩子

case3:key的叔叔節點是黑色且key是乙個左孩子

void rb_insert_fix(rbt* root, rbt* key)

else if (key == key->p->right)

key->p->color = black;

key->p->p->color = red;

right_rotate(root, key->p->p);

//case 3: father node is red,uncle node is black,key is the left child

} else

else if (key == key->p->left)

key->p->color = black;

key->p->p->color = red;

left_rotate(root, key->p->p);

} }root->color = black;

}

紅黑樹放棄了追求完全平衡,追求大致平衡,在與平衡二叉樹的時間複雜度相差不大的情況下,保證每次插入最多隻需要三次旋轉就能達到平衡,實現起來也更為簡單。

紅黑樹(演算法導論)

測試 所用的例子為算導第三版p179圖13 4 include using namespace std const bool black 0 黑色 const bool red 1 紅色 struct node 結點結構 class rb tree 初始化nil結點和root node left r...

演算法導論 紅黑樹

原文 組內培訓,講紅黑樹,找出演算法導論,啃了乙個週末,其中插入結點很簡單,刪除結點有點複雜,但跟著演算法導論上一步一步來沒有什麼問題。不想備份blog的,所以沒有把上穿。可直接察看ppt。紅黑樹性質 1.每個節點或是紅的,或是黑的 2.根節點是黑的 3.每個葉結點 nil 都是黑的 4.如果乙個結...

演算法導論學習筆記 紅黑樹

紅黑樹的5個性質 1 每個結點要麼是紅的,要麼是黑的。2 根結點是黑的。3 每個葉結點,即空結點 nil 是黑的。4 如果乙個結點是紅的,那麼它的倆個兒子都是黑的。5 對每個結點,從該結點到其子孫結點的所有路徑上包含相同數目的黑結點。public class rbtree 當在某個結點nodex上,...