紅黑樹插入時的情況
紅黑樹是有序樹,在插入乙個節點時,插入的結點一定會成為葉結點,且插入的結點一定要是紅色的。那麼,插入時就可能會產生顏色衝突,即插入結點 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.父節點為紅色,叔節點為紅色 對於這種情況,同時改變父 叔節點顏色為黑色,並將...