測試代碼所用的例子爲算導第三版p179圖13-4
#include <iostream>
using namespace std;
const bool BLACK = 0; // 黑色
const bool RED = 1; // 紅色
struct node // 結點結構
{
node *left;
node *right;
node *parent;
int key;
bool color;
node(node *init, int data) : left(init), right(init), parent(init), key(data), color(BLACK) {}
};
class RB_tree
{
public:
node *root; // 指向根結點
node *nil; // 空節點(哨兵)(黑色)
RB_tree(){ nil = new node(nullptr, -1); root = nil; } // 初始化nil結點和root
node *left_rotate(node *x); // 左旋
node *right_rotate(node *x); // 右旋
void RB_insert(node *z); // 插入一個結點
void RB_insert_fixup(node *z); // 插入後調整
node *tree_minimum(node *x); // 找最小值
node *tree_successor(node *x); // 找到x的後繼
node *RB_search(node *x, int k); // 查找元素
node *RB_delete(node *z); // 刪除一個結點
void RB_delete_fixup(node *x); // 刪除後調整
void RB_print(node *x);
void print();// 輸出
};
node *RB_tree::left_rotate(node *x) // 先將y的左孩子變爲x的右孩子(y有做孩子的話)
{ // 然後讓y成爲x父節點的右孩子(x爲根節點的話 y直接變爲根節點)
node *y = x->right; // 最後讓x變爲y的左孩子
x->right = y->left;
if (y->left != nil)
{
y->left->parent = x;
}
y->parent = x->parent;
if (x->parent == nil)
{
root = y;
}
else if (x->parent->left == x)
{
x->parent->left = y;
}
else
{
x->parent->right = y;
}
y->left = x;
x->parent = y;
return y;
}
node *RB_tree::right_rotate(node *x) // y的右孩子成爲x的左孩子 y成爲x父親的孩子 x成爲y的右孩子
{
node *y = x->left;
x->left = y->right;
if (y->right != nil)
{
y->right->parent = x;
}
y->parent = x->parent;
if (x->parent == nil)
{
root = y;
}
if (x->parent->right == x)
{
x->parent->right = y;
}
else
{
x->parent->left = y;
}
y->right = x;
x->parent = y;
return y;
}
void RB_tree::RB_insert(node *z)
{
node *y = nil;
node *x = root;
// 利用x不斷向下並賦值給y 找到z的插入點
while (x != nil)
{
y = x;
if (z->key < x->key)
{
x = x->left;
}
else
{
x = x->right;
}
}
// 將 z插入到y的合適部位
z->parent = y;
if (y == nil) // 樹空的時候 z成爲根結點
{
root = z;
}
else if (z->key < y->key)
{
y->left = z;
}
else
{
y->right = z;
}
// 調整先插入的z的屬性 然後調整 保持樹的性質
z->left = nil;
z->right = nil;
z->color = RED; // 必須爲紅 黑的話 會破壞樹的性質
RB_insert_fixup(z); // 向上調整維護樹的性質
}
void RB_tree::RB_insert_fixup(node *z)
{
node *y;
while (z->parent->color == RED)
{
if (z->parent == z->parent->parent->left)
{
y = z->parent->parent->right;
if (y->color == RED) // case 1 z的叔節點是紅色的
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else // case 2 z的叔節點黑色且z是右孩子
{
if (z == z->parent->right)
{
z = z->parent;
left_rotate(z);
}
z->parent->color = BLACK; // case 3 z的叔節點是黑色的且z是左孩子
z->parent->parent->color = RED;
right_rotate(z->parent->parent);
}
}
else if (z->parent == z->parent->parent->right) // p[z]爲右孩子的時候 與上面對稱
{
y = z->parent->parent->left;
if (y->color == RED)
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else
{
if (z == z->parent->left)
{
z = z->parent;
right_rotate(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
left_rotate(z->parent->parent);
}
}
}
root->color = BLACK; // 根結點調整爲黑色
}
node *RB_tree::tree_minimum(node *x) // 求最小值
{
while (x->left != nil)
{
x = x->left;
}
return x;
}
node *RB_tree::tree_successor(node *x) // 尋找元素的後繼
{
if (x->right != nil) // 右子樹不爲空的話 在右子樹中找到最小值就是
{
return tree_minimum(x->right);
}
node *y = x->parent; // 一直向上尋找
while (y != nil && x == y->right)
{
x = y;
y = y->parent;
}
return y;
}
node *RB_tree::RB_search(node *x, int k) // 尋找某個元素
{
if (x->key == -1 || k == x->key)
{
return x;
}
if (k < x->key)
{
return RB_search(x->left, k);
}
else
{
return RB_search(x->right, k);
}
}
node *RB_tree::RB_delete(node *z) // 刪除某個元素 與BST基本一樣
{
node *x, *y;
if (z->left == nil || z->right == nil)
y = z;
else
y = tree_successor(z);
if (y->left != nil)
x = y->left;
else
x = y->right;
x->parent = y->parent; // 不需要判斷x是否爲nil 無條件執行 BST要執行判斷
if (y->parent == nil)
{
root = x;
}
else if (y == y->parent->left)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
if (y != z)
{
z->key = y->key;
}
if (y->color == BLACK) // 如果刪除的是黑色結點 則向上調整樹的性質 刪除的是紅色的什麼也不影響 直接刪掉即可
{
RB_delete_fixup(x);
}
return y;
}
void RB_tree::RB_delete_fixup(node *x) // 假設刪除的y的黑色給了x x有了兩層黑色這樣可以滿足性質5 只需要調整性質1 2 4即可
{
node *w; // x的叔節點
while (x != root && x->color == BLACK) //while循環的目的是將額外的黑色沿樹上移(循環內部x時鐘指向雙重黑色結點)
{ // 直到 1.x指向紅黑結點,最後將x着色爲(單個)黑
if (x == x->parent->left) // 2.x指向根節點 此時可以簡單的移除額外的黑色
{ // 3.執行適當的旋轉和重新着色 退出循環
w = x->parent->right;
if (w->color == RED) // case 1
{
w->color = BLACK;
x->parent->color = RED;
left_rotate(x->parent);
w = x->parent->right;
}
if (w->left->color == BLACK && w->right->color == BLACK) // case 2
{
w->color = RED;
x = x->parent;
}
else
{
if (w->right->color == BLACK) // case 3
{
w->left->color = BLACK;
w->color = RED;
right_rotate(w);
w = x->parent->right;
}
w->color = x->parent->color; // case 4
x->parent->color = BLACK;
w->right->color = BLACK;
left_rotate(x->parent);
x = root;
}
}
else if (x == x->parent->right) // x是右孩子的是 與上面對稱的過程
{
w = x->parent->left;
if (w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
right_rotate(x->parent);
w = x->parent->left;
}
if (w->right->color == BLACK && w->left->color == BLACK)
{
w->color = RED;
x = x->parent;
}
else
{
if (w->left->color == BLACK)
{
w->right->color = BLACK;
w->color = RED;
left_rotate(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
right_rotate(x->parent);
x = root;
}
}
}
x->color = BLACK; // 目的是把新結點染爲單一黑色
}
void RB_tree::RB_print(node *x)
{
if (x->key == -1)
{
return;
}
RB_print(x->left);
cout << x->key << " " << x->color << endl;
RB_print(x->right);
}
void RB_tree::print() // 中序遍歷樹 全部輸出
{
RB_print(root);
cout << endl;
}
int main()
{
RB_tree T;
int s[9] = {7,2,11,1,5,8,14,4,15};
for (int i = 0; i < 9; ++i)
{
node *z = new node(T.nil, s[i]);
T.RB_insert(z);
T.print();
}
cout << (*(T.root)).key << endl;
T.RB_delete(T.root);
cout << endl;
T.print();
return 0;
}