经过两三天的探索,终于把红黑树的实现完成了。难点主要在于理解删除时对于多一重颜色的理解。
另外,对于插入和删除的修正原理有一定的了解。特别是删除时候4种情况的判断以及对应措施,非常经典。
red_black_tree.h
#pragma once
/*************************************************
Author:董小歪
Date:2016-06-13
Description:算法导论第十三章-红黑树-Cpp代码实现
**************************************************/
#ifndef RED_BLACK_TREE
#define RED_BLACK_TREE
#include <iostream>
using namespace std;
enum Color {RED, BLACK};
struct TreeNode
{
Color color;
int key;
TreeNode *left, *right, *p;
TreeNode(int _key = 0) :color(RED), key(_key), left(nullptr), right(nullptr), p(nullptr) {}
};
class RedBlackTree
{
public:
RedBlackTree(); //构造函数
void rb_insert(int key); //插入
void inorder_tree_walk(); //中序遍历红黑树
void rb_delete(int key); //删除结点
TreeNode* tree_search(int val); //元素搜索
private:
TreeNode *root;
void rb_insert_fixup(TreeNode* z); //插入修正
void left_rotate(TreeNode* x); //左旋
void right_rotate(TreeNode* x); //右旋
void inorder_tree_walk(TreeNode* node); //中序遍历红黑树
void rb_transplant(TreeNode* u, TreeNode* v);
void rb_delete_fixup(TreeNode* x); //删除修正
TreeNode* tree_search(TreeNode* node, int val);
TreeNode* tree_minimun(TreeNode* node); //最小元素
};
#endif // !RED_BLACK_TREE
#include "red_black_tree.h"
RedBlackTree::RedBlackTree():root(nullptr){}
void RedBlackTree::left_rotate(TreeNode* x)
{
//左旋和右旋一共要改变6个指针的指向
TreeNode *y = x->right;
x->right = y->left;
if (y->left)
y->left->p = x;
y->p = x->p;
if (x->p == nullptr)
root = y;
else if (x->p->left == x)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p = y;
}
void RedBlackTree::right_rotate(TreeNode* x)
{
TreeNode* y = x->left;
x->left = y->right;
if (y->right)
y->right->p = x;
y->p = x->p;
if (x->p == nullptr)
root = y;
else if (x->p->left == x)
x->p->left = y;
else
x->p->right = y;
y->right = x;
x->p = y;
}
void RedBlackTree::rb_insert(int key)
{
TreeNode* z = new TreeNode(key);
TreeNode* y = nullptr;
TreeNode* x = root;
while (x)
{
y = x;
if (key < x->key)
x = x->left;
else
x = x->right;
}
z->p = y;
if (y == nullptr)
root = z;
else if (key < y->key)
y->left = z;
else
y->right = z;
rb_insert_fixup(z);
}
void RedBlackTree::rb_insert_fixup(TreeNode* z)
{
while (z->p && z->p->color == RED)
{
if (z->p->p->left == z->p)
{
TreeNode *y = z->p->p->right;
if (y && y->color == RED) //case 1
{
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}
else
{
if (z == z->p->right) //case 2
{
z = z->p;
left_rotate(z);
} //case 3
z->p->color = BLACK;
z->p->p->color = RED;
right_rotate(z->p->p);
}
}
else
{
TreeNode *y = z->p->p->left;
if (y && y->color == RED)
{
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}
else
{
if (z == z->p->left)
{
z = z->p;
right_rotate(z);
}
z->p->color = BLACK;
z->p->p->color = RED;
left_rotate(z->p->p);
}
}
}
root->color = BLACK;
}
void RedBlackTree::inorder_tree_walk()
{
inorder_tree_walk(root);
}
void RedBlackTree::inorder_tree_walk(TreeNode* node)
{
if (node)
{
inorder_tree_walk(node->left);
cout << node->key << ":" << (node->color == RED ? "RED" : "BLACK") << " ";
inorder_tree_walk(node->right);
}
}
void RedBlackTree::rb_delete(int key)
{
TreeNode *z = tree_search(key);
TreeNode *x;
if (z == nullptr)
{
cout << "关键字为" << key << "的元素不存在,无法删除!" << endl;
return;
}
TreeNode *y = z;
Color original_color = y->color;
if (z->left == nullptr)
{
x = z->right;
rb_transplant(z, z->right);
}
else if (z->right == nullptr)
{
x = z->left;
rb_transplant(z, z->left);
}
else
{
y = tree_minimun(z->right);
original_color = y->color;
x = y->right;
if (y->p == z)
{
if (x)
x->p == y;
}
else
{
rb_transplant(y, y->right);
y->right = z->right;
y->right->p = y;
}
rb_transplant(z, y);
y->left = z->left;
y->left->p = y;
y->color = z->color;
}
if (original_color == BLACK)
rb_delete_fixup(x);
}
void RedBlackTree::rb_transplant(TreeNode* u, TreeNode* v)
{
if (u->p == nullptr)
root = v;
else if (u == u->p->left)
u->p->left = v;
else
u->p->right = v;
if (v)
v->p = u->p;
}
void RedBlackTree::rb_delete_fixup(TreeNode* x)
{
if (x == nullptr)
return;
while (x != root && x->color == BLACK)
{
if (x == x->p->left)
{
TreeNode* w = x->p->right;
if (w->color == RED) //case 1
{
w->color = BLACK;
x->p->color = RED;
left_rotate(x->p);
w = x->p->right;
}
if (w->left->color == BLACK && w->right->color == BLACK) //case 2
{
w->color = RED;
x = x->p;
}
else
{
if (w->right->color == BLACK) //case 3
{
w->left->color = BLACK;
w->color = RED;
right_rotate(w);
w = x->p->right;
}
w->color = x->p->color; //case 4
x->p->color = BLACK;
w->right->color = BLACK;
left_rotate(x->p);
x = root;
}
}
else
{
TreeNode* w = x->p->left;
if (w->color == RED)
{
w->color = BLACK;
x->p->color = RED;
right_rotate(x->p);
w = x->p->left;
}
if (w->right->color == BLACK && w->left->color == BLACK)
{
w->color = RED;
x = x->p;
}
else
{
if (w->left->color == BLACK)
{
w->right->color = BLACK;
w->color = RED;
left_rotate(w);
w = x->p->left;
}
w->color = x->p->color;
x->p->color = BLACK;
w->left->color = BLACK;
right_rotate(x->p);
x = root;
}
}
}
x->color = BLACK;
}
TreeNode* RedBlackTree::tree_search(int val)
{
return tree_search(root, val);
}
TreeNode* RedBlackTree::tree_search(TreeNode* node, int val)
{
if (!node || node->key == val)
return node;
if (val < node->key)
return tree_search(node->left, val);
else
return tree_search(node->right, val);
}
TreeNode* RedBlackTree::tree_minimun(TreeNode* node)
{
TreeNode* temp = node;
while (temp && temp->left)
temp = temp->left;
return temp;
}
测试:
main_entrance.cpp
#include "red_black_tree.h"
int main()
{
cout << "创建红黑树:" << endl; RedBlackTree rbt;
cout << endl << "插入元素11:"; rbt.rb_insert(11); rbt.inorder_tree_walk();
cout << endl << "插入元素10:"; rbt.rb_insert(10); rbt.inorder_tree_walk();
cout << endl << "插入元素12:"; rbt.rb_insert(12); rbt.inorder_tree_walk();
cout << endl << "插入元素9:"; rbt.rb_insert(9); rbt.inorder_tree_walk();
cout << endl << "插入元素7:"; rbt.rb_insert(7); rbt.inorder_tree_walk();
cout << endl << "插入元素15:"; rbt.rb_insert(15); rbt.inorder_tree_walk();
cout << endl << "插入元素5:"; rbt.rb_insert(5); rbt.inorder_tree_walk();
cout << endl << "插入元素8:"; rbt.rb_insert(8); rbt.inorder_tree_walk();
cout << endl << "插入元素4:"; rbt.rb_insert(4); rbt.inorder_tree_walk();
cout << endl << "删除元素5(黑):"; rbt.rb_delete(5); rbt.inorder_tree_walk();
cout << endl << "删除元素11(红):"; rbt.rb_delete(11); rbt.inorder_tree_walk();
cout << endl;
system("pause");
}
测试结果: