算法导论的红黑树讲解很好,插入的调整比较容易懂,但是删除的调整就有点难懂了,书里也没证明为什么那样做就能够保持性质(留做练习题了),虽然可以理解过程。
比较好玩的一点是,比较上次写的二叉搜索树,随机插入1000000个结点是二叉搜索树高度为48(不稳定,很容易变到50+),而红黑树的高度为24(很稳定)!而log2(1000000) = 20,也可以说明红黑树的平衡性确实是比较好的!
贴下代码,以后再来证明;
// RedBlackTree.h
#ifndef __RED_BLACK_TREE_H__
#define __RED_BLACK_TREE_H__
#include <iostream>
using namespace std;
struct TreeNode
{
static TreeNode* NIL;
enum COLOR
{
RED, BLACK
};
int value;
COLOR color;
TreeNode *left, *right, *parent;
TreeNode(int value, bool isNIL=false, COLOR color=RED)
: value(value), left(NIL), right(NIL), parent(NIL), color(color) {}
};
class RedBlackTree
{
public:
RedBlackTree();
bool insert(int value);
bool deleteNode(int value);
bool deleteNode(TreeNode* node);
void display(char spliter=' ') const;
size_t height() const;
private:
void displayHelper(TreeNode* root, char spliter) const;
size_t getHeight(const TreeNode* root) const;
void leftRotate(TreeNode* root);
void rightRotate(TreeNode* root);
void RBInsertFixup(TreeNode* node);
void tranplant(TreeNode* from, TreeNode* to);
TreeNode* getTreeMinimum(TreeNode* root) const;
void RBDeleteFixup(TreeNode* node);
private:
TreeNode* m_root;
};
#endif
// RedBlackTree.cpp
#include "RedBlackTree.h"
TreeNode* TreeNode::NIL = new TreeNode(0, TreeNode::BLACK);
RedBlackTree::RedBlackTree() {
m_root = TreeNode::NIL;
}
bool RedBlackTree::insert(int value) {
TreeNode *lastNode = TreeNode::NIL, *now = m_root, *toInsert = new TreeNode(value);
while (now != TreeNode::NIL) {
lastNode = now;
if (value == now->value)
return false;
else if (value < now->value)
now = now->left;
else
now = now->right;
}
toInsert->parent = lastNode;
if (lastNode == TreeNode::NIL) {
m_root = toInsert;
} else if (value < lastNode->value) {
lastNode->left = toInsert;
} else {
lastNode->right = toInsert;
}
RBInsertFixup(toInsert);
return true;
}
bool RedBlackTree::deleteNode(int value) {
TreeNode *now = m_root;
while (now != TreeNode::NIL) {
if (value == now->value) {
return deleteNode(now);
} else if (value < now->value) {
now = now->left;
} else {
now = now->right;
}
}
return false;
}
bool RedBlackTree::deleteNode(TreeNode* node) {
if (node == TreeNode::NIL)
return false;
TreeNode *toDelete = node, *recover_point;
TreeNode::COLOR original_color = toDelete->color;
if (node->left == TreeNode::NIL) {
recover_point = node->right;
tranplant(node, node->right);
} else if (node->right == TreeNode::NIL) {
recover_point = node->left;
tranplant(node, node->left);
} else {
toDelete = getTreeMinimum(toDelete->right);
recover_point = toDelete->right;
original_color = toDelete->color;
if (toDelete->parent == node) {
// later...
recover_point->parent = toDelete;
} else {
tranplant(toDelete, toDelete->right);
toDelete->right = node->right;
node->right->parent = toDelete;
}
tranplant(node, toDelete);
toDelete->left = node->left;
node->left->parent = toDelete;
toDelete->color = node->color;
}
// delete node;
if (original_color == TreeNode::BLACK) {
RBDeleteFixup(recover_point);
}
return true;
}
// 前序输出
void RedBlackTree::display(char spliter) const {
if (m_root == TreeNode::NIL) {
cout << "NULL" << endl;
return;
}
displayHelper(m_root, spliter);
cout << endl;
}
void RedBlackTree::displayHelper(TreeNode* root, char spliter) const {
if (root == TreeNode::NIL)
return;
displayHelper(root->left, spliter);
cout << root->value << spliter;
displayHelper(root->right, spliter);
}
size_t RedBlackTree::height() const {
return getHeight(m_root);
}
size_t RedBlackTree::getHeight(const TreeNode* root) const {
if (root == TreeNode::NIL)
return 0;
size_t left_height = getHeight(root->left);
size_t right_height = getHeight(root->right);
return max(left_height, right_height) + 1;
}
void RedBlackTree::leftRotate(TreeNode* root) {
TreeNode* newSubRoot = root->right;
root->right = newSubRoot->left;
if (newSubRoot->left != TreeNode::NIL) {
newSubRoot->left->parent = root;
}
newSubRoot->parent = root->parent;
if (root->parent == TreeNode::NIL) {
m_root = newSubRoot;
} else if (root == root->parent->left) {
root->parent->left = newSubRoot;
} else {
root->parent->right = newSubRoot;
}
root->parent = newSubRoot;
newSubRoot->left = root;
}
void RedBlackTree::rightRotate(TreeNode* root) {
TreeNode* newSubRoot = root->left;
root->left = newSubRoot->right;
if (newSubRoot->right != TreeNode::NIL) {
newSubRoot->right->parent = root;
}
newSubRoot->parent = root->parent;
if (root->parent == TreeNode::NIL) {
m_root = newSubRoot;
} else if (root == root->parent->left) {
root->parent->left = newSubRoot;
} else {
root->parent->right = newSubRoot;
}
newSubRoot->right = root;
root->parent = newSubRoot;
}
void RedBlackTree::RBInsertFixup(TreeNode* node) {
// cout << "going to fixup... " << node << ' ' << node->value << ' ' << node->parent << endl;
while (node->parent != TreeNode::NIL && node->parent->color == TreeNode::RED) {
if (node->parent == node->parent->parent->left) {
// cout << "fixing... " << node->value << endl;
TreeNode* uncle = node->parent->parent->right;
if (uncle->color == TreeNode::RED) {
uncle->color = TreeNode::BLACK;
node->parent->color = TreeNode::BLACK;
node->parent->parent->color = TreeNode::RED;
node = node->parent->parent;
} else {
if (node == node->parent->right) {
node = node->parent;
leftRotate(node);
}
node->parent->color = TreeNode::BLACK;
node->parent->parent->color = TreeNode::RED;
rightRotate(node->parent->parent);
}
} else {
// cout << "fixing... " << node->value << endl;
TreeNode* uncle = node->parent->parent->left;
if (uncle->color == TreeNode::RED) {
uncle->color = TreeNode::BLACK;
node->parent->color = TreeNode::BLACK;
node->parent->parent->color = TreeNode::RED;
node = node->parent->parent;
} else {
if (node == node->parent->left) {
node = node->parent;
rightRotate(node);
}
node->parent->color = TreeNode::BLACK;
node->parent->parent->color = TreeNode::RED;
leftRotate(node->parent->parent);
}
}
}
m_root->color = TreeNode::BLACK;
}
void RedBlackTree::tranplant(TreeNode* from, TreeNode* to) {
if (from->parent == TreeNode::NIL) {
m_root = to;
} else if (from = from->parent->left) {
from->parent->left = to;
} else {
from->parent->right = to;
}
to->parent = from->parent;
}
TreeNode* RedBlackTree::getTreeMinimum(TreeNode* root) const {
TreeNode* now = root;
while (now->left != NULL)
now = now->left;
return now;
}
void RedBlackTree::RBDeleteFixup(TreeNode* node) {
while (node != TreeNode::NIL && node != m_root && node->color == TreeNode::BLACK) {
if (node == node->parent->left) {
TreeNode* brother = node->parent->right;
// case 1: brother->color is RED
if (brother->color == TreeNode::RED) {
brother->color = TreeNode::BLACK;
node->parent->color = TreeNode::RED;
leftRotate(node->parent);
brother = node->parent->right;
}
// case 2: brother->color is BLACK and brother's two children's color are all BLACK
if (brother->left->color == TreeNode::BLACK && brother->right->color == TreeNode::BLACK) {
brother->color = TreeNode::RED;
node = node->parent;
} else {
// case 3: brother->color is BLACK and brother's left child's color is RED
// while right child's color is BLACK
// case 3 will be transformed to case 4
if (brother->right->color == TreeNode::BLACK) {
brother->left->color = TreeNode::BLACK;
brother->color = TreeNode::RED;
rightRotate(brother);
brother = node->parent->right;
}
// case 4: brother->color is BLACK and brother's right child'color is RED
brother->right->color = TreeNode::BLACK;
brother->color = node->parent->color;
node->parent->color = TreeNode::BLACK;
leftRotate(node->parent);
node = m_root;
}
} else {
TreeNode* brother = node->parent->left;
// case 1
if (brother->color == TreeNode::RED) {
brother->color = TreeNode::BLACK;
node->parent->color = TreeNode::RED;
rightRotate(node->parent);
brother = node->parent->left;
}
// case 2
if (brother->left->color == TreeNode::BLACK && brother->right->color == TreeNode::BLACK) {
brother->color = TreeNode::RED;
node = node->parent;
} else {
// case 3
if (brother->left->color == TreeNode::BLACK) {
brother->right->color = TreeNode::BLACK;
brother->color = TreeNode::RED;
leftRotate(brother);
brother = node->parent->left;
}
// case 4
brother->left->color = TreeNode::BLACK;
brother->color = node->parent->color;
node->parent->color = TreeNode::BLACK;
rightRotate(node->parent);
node = m_root;
}
}
}
node->color = TreeNode::BLACK;
}
// main.cpp
#include "RedBlackTree.h"
#include <iostream>
#include <stdlib.h>
#include <ctime>
using namespace std;
const int MAX = 100000;
inline int randInt() {
return rand() % MAX;
}
int main() {
srand(time(0));
RedBlackTree rbt;
for (int i = 0; i < MAX; ++i)
rbt.insert(randInt());
// rbt.display();
cout << "tree height = " << rbt.height() << endl << endl;
for (int i = 0; i < MAX; ++i) {
bool result = rbt.deleteNode(i);
if (result)
cout << "delete success ";
else
cout << "delete fail ";
cout << i << "\ttree height = " << rbt.height() << endl;
// rbt.display();
cout << endl;
}
return 0;
}