紅黑樹的插入操作

2021-10-23 16:24:17 字數 3193 閱讀 8870

紅黑樹插入時的情況

紅黑樹是有序樹,在插入乙個節點時,插入的結點一定會成為葉結點,且插入的結點一定要是紅色的。那麼,插入時就可能會產生顏色衝突,即插入結點 n 和 它的父節點 p 的顏色都是紅色。如果 p 是黑色,沒有衝突,直接插入就好。

顏色衝突問題解決

要明確,在紅黑樹插入節點 n 時,如果出現顏色衝突,一定需要關注它的叔叔節點 u,這時,自然要先找到 n 的祖父節點 gp。

情況分析

衝突時,n 和 p 都是紅的,因為樹本身原本是一顆紅黑樹,此時 gp 一定存在且為黑。分析 u 的情況:

—— u 紅

———— p 和 u 塗黑,gp塗紅,使 n=gp,然後去觀察 n 和 n 的父親 p 的情況,如果顏色衝突就重複這一步驟,如果不衝突,則下面的步驟也不需要進行。

—— u 黑或 u 不存在

———— 這時,n 和 p 都是紅色,如果 n 和 p 不同邊(n 和 p 乙個是左孩子,乙個是右孩子),則需要進行第一次的旋轉操作(以 p 為中心旋轉,旋轉之後,n 和 p 同邊),旋轉之後,n 會在 p 的上面,使 n=p、p=n->parent。這時,將 p 塗黑,gp 塗紅,然後以 gp 進行第二次的旋轉,使紅黑樹重新平衡。

解釋u 紅時進行的操作,不會改變紅黑樹根結點到葉結點的路徑中黑色節點的個數,在操作過程中,可能不需要進行下一步的操作(旋轉),就已經平衡了。

u 黑時進行的操作,此時可能需要以 p 進行旋轉(左旋或右旋),第一次的旋轉不會改變結點顏色,也不會改變路徑中黑節點的個數,它是為了第二次的旋轉準備的,因為第二次旋轉必須是同邊的。當 n 和 p 同邊後,會對 p 和 gp 重新著色,著色以後,路徑中黑節點的個數發生了變化,以 gp 進行的第二次旋轉使得路徑中黑色結點的個數恢復,由此可以知道,插入操作最多隻會造成兩次的旋轉操作。

**

enum col

;//這裡表示顏色

typedef

int t;

typedef

struct rbnoderbnode;

typedef

struct rbnode* rbtree;

//定義rbtree

//表示節點是左孩子還是右孩子

enum dire

;//建立乙個結點,傳入父節點位址,返回建立結點的指標

rbnode *

rbtree_create_rbnode

(t data,rbnode *parent)

return node;

}/*以 node 為中心進行左旋,ptree是指向根節點的指標

|| ||

node nr

/ \ --> / \

nl nr node r

/ \ / \

l r nl l

需要處理的有node->parent->right(或->left)、nr->left、nr->parent、l->parent、node->right、node->parent

*/void

left_rotation

(rbtree *ptree,rbnode *node)

else

else

}//處理node->right

node->right = right->left;

if(node->right !=

null

)//處理nr->left

right->left = node;

//處理node->parent

node->parent = right;}/*

|| ||

node nl

/ \ --> / \

nl nr l node

/ \ / \

l r r nr

*/void

right_rotation

(rbtree *ptree,rbnode *node)

else

else

} node->left = left->right;

if(node->left !=

null

) node->parent = left;

left->right = node;

}//調節紅黑樹的平衡,ptree為根結點,node為插入時的結點

void

rbtree_insert_repair

(rbtree *ptree,rbnode *node)

//這裡開始,node 沒有 uncle,或者 uncle 為黑

if(nd != pd)

else

node = parent;

parent = node->parent;

}//在這裡,由於同邊的紅紅衝突,n 和 p 為紅,gp 黑

gp->col = red;

parent->col = black;

//經過上述處理 同邊 以 gp 旋轉

if(pd == l)

else

break;}

(*ptree)

->col = black;

//紅黑樹根節點必須是黑的,上數過程中,可能會將根節點染紅

}//插入結點 並 調節紅黑樹

intrbtree_insert

(rbtree *ptree,t data,

int(

*compar)

(t,t)

)else

if(ret >0)

else

}*ptree =

rbtree_create_rbnode

(data,parent);if

(*ptree ==

null

)rbtree_insert_repair

(proot,

*ptree)

;return0;

}

紅黑樹筆記 紅黑樹的插入操作

紅黑樹的插入操作可以在o logn 的時間內完成。開始插入節點的時候和二叉查詢樹一樣,只需要最後將插入的節點著成紅色,為了保證紅黑樹的性質,需要通過rb insertfixup函式來調整該節點,對其重新著色並旋轉。下面先呼叫rb insert 函式將乙個節點插入到紅黑樹中,同樣先上偽 rb inse...

紅黑樹的插入操作詳解

每個節點或者是黑色節點,後者是紅色節點 根節點是黑色節點 每個葉子節點 null節點 是黑色節點 若乙個節點是紅色節點,那麼它的所有子節點都是黑色節點 從任意乙個非葉子節點出發,到達葉子節點,其中所有路徑經過的黑色節點的數目是相同的 以上5個特點決定紅黑樹中,從乙個非葉子節點出發到達葉子節點,其中最...

紅黑樹(插入)

紅黑樹的插入操作相對刪除操作比較簡單。紅黑樹要滿足 任一節點至null的任何路徑,所含黑節點數必須相同。所以,為了滿足此性質,插入節點應該為紅色。如果插入節點的父親為黑色,則不需要進行調整,若為紅色,有三種情況需要討論。1.父節點為紅色,叔節點為紅色 對於這種情況,同時改變父 叔節點顏色為黑色,並將...