紅黑樹插入和刪除的各種情況分析

2021-10-14 11:08:45 字數 4075 閱讀 5792

紅黑樹是一種自平衡的二叉查詢樹,是一種高效的查詢樹,定義如下:

每個節點是紅色或黑色

根是黑色

所有葉子都是黑色(葉子是nil節點)

如果乙個節點是紅色的,則他的兩個兒子是黑色的(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點(簡稱黑高)

typedef

int key_type;

//定義紅黑樹的節點

typedef

struct _rbtree_node rbtree_node;

//定義紅黑樹整棵樹

//root為根節點

//所有的葉子節點指向nil(以前我也覺得沒必要,後來發現這樣判斷葉子節點挺好用的)

左旋步驟:

1)修改x的"右兒子指標"指向b

2)修改b的"父親指標"指向x

3)修改y的"父親指標"指向z

4)修改z的"(左或者右)兒子指標"指向y

5)修改y的"左兒子指標"指向x

6)修改x的"父親指標"指向y

**如下:(注意:判斷b是否為葉子和傳入的節點是根節點還是左右節點)

void

rbtree_left_rotate

(rbtree *t, rbtree_node *x)

y->parent = x->parent;

//3if

(x->parent == t->nil)

else

if(x == x->parent->left)

else

y->left = x;

//5 x->parent = y;

//6}

右旋步驟:

1)修改y的"左兒子指標"指向b

2)修改b的"父親指標"指向y

3)修改x的"父親指標"指向z

4)修改z的"(左或者右)兒子指標"指向x

5)修改x的"右兒子指標「指向y

6)修改y的」父親指標「指向x

**如下:(注意:判斷b是否為葉子和傳入的節點是根節點還是左右節點)

void

rbtree_right_rotate

(rbtree *t, rbtree_node *y)

x->parent = y->parent;

//3if

(y->parent == t->nil)

else

if(y == y->parent->right)

else

x->right = y;

//5 y->parent = x;

//6}

1)根據要插入的key的值,找到葉子結點並插入。

2)判斷當前結點key的父節點是否為黑色,是則退出,否則進入第三步。

3)判斷當前結點key叔叔節點是否為紅色,是則進去第四步,否則進入第五步。

4)將當前結點key的祖父節點變紅,key的父節點和叔叔節點變黑,在將當前結點指向祖父節點並回到第二步。(筆記:因為父親是紅色節點,所以祖父肯定不是紅色節點,是黑色節點)

5)判斷當前結點key的父親節點是否為祖父節點的左兒子,是則進入第六步,否則進入第八步。

6)判斷當前結點key是否為父親節點的左兒子,是則進入第七步,否則對當前節點key的父親節點進行左旋,再進入第七步。(注意:經過左旋後,當前節點上去了,曾經的父親節點下來了,當前節點key指向的是下來的節點(曾經的父親節點))

7)將當前結點key的父親節點變色為黑色,祖父節點變色為紅色,最後將當前節點key指向祖父節點,對當前節點key進行右旋,並返回第二步。(筆記:經過右旋後,當前節點肯定是黑色,因為他是曾經的父親節點旋轉上來的)

8)判斷當前結點key是否為父親節點的右兒子,是則進入第七步,否則對當前節點key的父親節點進行右旋,再進入第九步。(注意:經過右旋後,當前節點上去了,曾經的父親節點下來了,當前節點key指向的是下來的節點(曾經的父親節點))

9)將當前結點key的父親節點變色為黑色,祖父節點變色為紅色,最後將當前節點key指向祖父節點,對當前節點key進行左旋,並返回第二步。(筆記:經過左旋後,當前節點肯定是黑色,因為他是曾經的父親節點旋轉上來的)

void

rbtree_insert_fixup

(rbtree *t, rbtree_node *z)

else

z->parent->color = black;

z->parent->parent->color = red;

rbtree_right_rotate

(t, z->parent->parent);}

}else

else

z->parent->color = black;

z->parent->parent->color = red;

rbtree_left_rotate

(t, z->parent->parent);}

}}t->root->color = black;

}void

rbtree_insert

(rbtree *t, rbtree_node *z)

else

if(z->key > x->key)

else

} z->parent = y;

if(y == t->nil)

else

if(z->key < y->key)

else

z->left = t->nil;

z->right = t->nil;

z->color = red;

rbtree_insert_fixup

(t, z)

;}

舉個例子在下面的紅黑樹中插入4這個節點

步驟一:找到4的位置,並且插進去,顏色為紅色,變為下圖

步驟二:當前節點(4)的父親節點(5)是紅色的,進入第三步,

步驟三:叔叔節點(8)是紅色的,進入第四步,

步驟四:將當前結點key的祖父節點(7)變紅,key的父節點(5)和叔叔節(8)點變黑,在將當前結點指向祖父節點(7)並回到第二步,變為下圖。

步驟二:當前節點(7)的父親節點(2)是紅色的,進入第三步,

步驟三:叔叔節點(14)是黑色的,進入第五步,

步驟五:當前節點(7)的父親節點(2)是為祖父節點(11)的左兒子,進入第六步

步驟六:當前節點(7)不是為父親節點(2)的左兒子,當前節點的父親節點(2)進行左旋,再進入第七步。(注意:經過左旋後,當前節點變為曾經的父親節點(2)了)

步驟七:將當前節點(2)的父親節點(11)變色為黑色,祖父節點(11)變色為紅色,最後將當前節點key指向祖父節點,對當前節點key進行右旋,並返回第二步。(筆記:經過右旋後,當前節點肯定是黑色,因為他是曾經的父親節點旋轉上來的),變為下圖。

步驟七:將當前節點(2)的父親節點(7)變色為黑色,祖父節點(11)變色為紅色,最後將當前節點指向祖父節點(11),對當前節點key進行右旋,並返回第二步。(筆記:經過右旋後,當前節點肯定是黑色,因為他是曾經的父親節點(7)旋轉上來的),變為下圖。

紅黑樹插入操作的各種情況分析

目錄 1.被插入的節點是根節點。2.被插入的節點的父節點是黑色。3.被插入的節點的父節點是紅色。3.1 叔叔結點為紅色 3.2 插入結點的父結點p是祖父結點pp的左子結點,插入結點的叔叔結點s不存在或為黑色 3.2.1 插入結點是父結點p的左子結點 3.2.2 插入結點是父結點p的右子結點 3.3 ...

紅黑樹的插入和刪除

上一章講述了紅黑樹得相關性質,我們了解到紅黑樹確實是平衡二叉樹,在時間複雜度為o lg n 比二叉搜尋樹效能更好,效能變好的前提是演算法更加複雜了,下面講述紅黑樹的插入和刪除操作,希望對大家有所幫助。紅黑樹的插入操作和二叉搜尋樹大致相同,不同點是在將節點x插入紅黑樹後,此時的紅黑樹可能會違反紅黑樹的...

關於紅黑樹的插入和刪除

定義 紅黑樹是一棵二叉搜尋樹。它在每個結點每個結點上新增乙個儲存位來表示顏色,可以是紅色或者黑色。通過對任何一條從根到葉子結點的簡單路徑上各個結點的顏色進行約束。紅黑樹保證確保沒有一條路徑會比其他路徑長出兩倍,因而近似是平衡的。性質 1 每個結點或者是紅色或者是黑色 2 根結點是黑色的 3 每個葉子...