算法导论:红黑树

算法导论的红黑树讲解很好,插入的调整比较容易懂,但是删除的调整就有点难懂了,书里也没证明为什么那样做就能够保持性质(留做练习题了),虽然可以理解过程。

比较好玩的一点是,比较上次写的二叉搜索树,随机插入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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值