紅黑樹(shù)實(shí)現(xiàn)
1、五個(gè)性質(zhì)
(1)根節(jié)點(diǎn)黑色
(2) 只有紅色和黑色節(jié)點(diǎn)
(3) 紅色節(jié)點(diǎn)相鄰節(jié)點(diǎn)黑色
(4) 每個(gè)節(jié)點(diǎn)到任意子樹(shù)葉子節(jié)點(diǎn)黑色節(jié)點(diǎn)個(gè)數(shù)相同
(5) 葉子節(jié)點(diǎn)黑色
2、插入
插入節(jié)點(diǎn)顏色為紅色
(1) 根節(jié)點(diǎn)為null 直接賦值
(2) 插入節(jié)點(diǎn)父親節(jié)點(diǎn)為黑色結(jié)束
(3) 插入節(jié)點(diǎn)父親節(jié)點(diǎn)顏色為紅色
1、叔叔節(jié)點(diǎn)顏色為紅色
b r
/ \ / \
r r -> b b
/ /
(r) (r)
2、叔叔節(jié)點(diǎn)為黑色
b b
/ \ / \
r b -> (r) r
/ \
(r) b
or
b b
/ \ / \
r b -> (r) b
\ /
(r) r
我的實(shí)現(xiàn)
if (rt->color == RED && par->color == RED) {
Node *grand = par->parent;
bool fc = (grand->ch[1] == par);
Node *uncle = grand->ch[fc ^ 1];
/*
* b r
* / \ / \
* r r -> b b
* / /
* (r) (r)
*
*/
if (uncle->color == RED) {
uncle->color = par->color = BLACK;
grand->color = RED;
} else {
bool c = (par->ch[1] == rt);
/**
* b b
* / \ / \
* r b -> (r) r
* / \
* (r) b
*/
if (c == fc) {
par->color = BLACK;
grand->color = RED;
rotate(par);
} else {
/**
* b b
* / \ / \
* r b -> (r) b
* \ /
* (r) r
*/
rotate(rt);
pushUp(rt->ch[c ^ 1]);
}
}
}
3、刪除
找到前繼節(jié)點(diǎn)或者后繼節(jié)點(diǎn),顏色不變,值互換下,然后開(kāi)始刪前繼或者后繼節(jié)點(diǎn),這個(gè)時(shí)候刪除其實(shí)有9種情況
(1) 根節(jié)點(diǎn)直接刪
(2) 紅色節(jié)點(diǎn)直接刪
(3) 刪除節(jié)點(diǎn)父親節(jié)點(diǎn)為紅色,父親變黑
(4) 子節(jié)為紅色的,變黑
然后就是紅黑樹(shù)里面最蛋疼的地方了一共五種情況,我們已經(jīng)刪除了節(jié)點(diǎn),要開(kāi)始平衡紅黑樹(shù),看代碼
/**
* delete balance
* @param rt
*/
void RedBlackTree::balance(Node *rt) {
if (rt == root) {
return;
}
Node *par = rt->parent;
bool c = par->isRightChild();
Node *brother = par->ch[c ^ 1];
/**
*
* B (B)
* / \ / \
* (B) B -----> B R
* / \ / \
* B B B B
*/
if (par->color == BLACK && brother->color == BLACK && brother->ch[c] == BLACK
&& brother->ch[c ^ 1] == BLACK) {
brother->color = RED;
balance(par);
return;
}
/**
* B1 B3
* / \ ----> /
* (B)2 R3 R1
* /
* (B)2
*
* grantee that brother is not red in the following
*/
if (brother->color == RED) {
std::swap(brother->color, par->color);
rotate(brother);
}
/**
* R (B)
* / \ / \
* (B) B -----> B R
* / \ / \
* B B B B
*/
assert(brother->color == BLACK);
brother = par->ch[c ^ 1];
if (par->color == RED && brother->color == BLACK && brother->ch[c] == BLACK
&& brother->ch[c ^ 1] == BLACK) {
std::swap(par->color, brother->color);
balance(par);
return;
}
/**
* X X
* / \ / \
* (B) B2 --> (B) B1
* / \ \
* R1 B3 R2
* \
* B3
*/
Node *left = brother->ch[c];
if (left->color == RED) {
std::swap(brother->color, left->color);
rotate(left);
}
/**
* X1 X2
* / \ / \
* (B) B2 -----> B1 B4
* / \ / \
* X3 R4 (B) X3
*/
Node *right = brother->ch[c ^ 1];
if (right->color == RED) {
std::swap(brother->color, par->color);
right->color = BLACK;
rotate(brother);
}
}
我的旋轉(zhuǎn)代碼 當(dāng)前節(jié)點(diǎn)往父親節(jié)點(diǎn)旋,這個(gè)可以根據(jù)自己的喜好來(lái)
void RedBlackTree::rotate(Node *rt) {
Node *father = rt->parent;
Node *grand = father->parent;
bool c = (father->ch[1] == rt);
bool fc = (grand->ch[1] == father);
Node *&ch = rt->ch[c ^ 1];
father->ch[c] = ch;
if (ch != nullNode) {
ch->parent = father;
}
ch = father;
ch->parent = rt;
rt->parent = grand;
grand->ch[fc] = rt;
if (father == root) {
root = rt;
}
maintain(father);
maintain(rt);
}