二叉树和红黑树的原理及实现

本文详细介绍了二叉树和红黑树的原理,包括它们的作用、性质以及插入和删除操作。二叉树用于快速查找,但存在极端情况导致效率降低,而红黑树通过五条性质保持平衡,提高查找效率。文中还提供了二叉树和红黑树的C++实现,包括插入、删除和查找等功能,并展示了如何维护红黑树的平衡性。
摘要由CSDN通过智能技术生成

二叉树和红黑树的原理及实现

二叉树的原理及作用

二叉树是一种特殊的树状结构,每一个结点最多只有两个孩子,左孩子比父结点小,右孩子比父结点大,所有结点都满足当前性质,等于父结点的情况可以放在右边也可以放在左边,放在右边可以保持稳定性。
可以用作非线性存储结构的快速查找,在非线性结构中,二叉树对数据进行排序,查找的效率从理论上说的O(log(n)),具有和二分查找同样的性质。但是二叉树会有极端情况,就是输入的数据相对有序,这样就趋近于线性表,查找速度趋近O(n)。有AVL(二叉平衡树)、红黑树等数据结构,基于二叉树解决了这类问题。

红黑树的作用

红黑树利用5条基本性质,相对解决了二叉树面对相对有序的数列不能较好处理的情况。插入和删除都可以保持这种特性,比较与AVL,红黑树维护的代价相对较低,所以C++ STL库中,map、set的底层就是使用红黑树实现的,中序遍历即为有序。epoll的底层数据结构也是红黑树,使用红黑树管理events的存储,需要大量的增删改查,红黑树是最优的数据结构。

红黑树的原理

红黑树5条基本性质
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点是黑色。(为空的叶子节点)
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

红黑树原理参考网页.
各种数据结构可视化模拟,最好使用google浏览器打开
红黑树维护自平衡分插入和删除两种。因为要满足以上五条性质,所以能少违背性质就少违背,基于这种想法,插入的结点就定义为红色,这样就只有可能违背第四条性质。

应对违背性质的操作,定义了左旋和右旋来维护红黑树的性质。

  1. 左旋:
    将父结点向左旋转为左子结点,右子结点旋转为父结点,其它结点保持二叉树的性质。
    将两个临时变量指向父结点和右子结点,具体操作6根指针:

      右子结点的父结点			=		父结点的父结点
      父结点的孩子(对应父结点)	=		右子结点
      父结点的父结点				=		右子结点
      父结点的右子结点			=		右子结点的左子结点
      右子结点的父结点			=		父结点	
      右子结点的左子结点			=		父结点
    
  2. 右旋:

      左子结点的父结点			=		父结点的父结点
      父结点的孩子(对应父结点)	=		左子结点
      父结点的父结点				=		左子结点
      父结点的左子结点			=		左子结点的右子结点
      左子结点的父结点			=		父结点	
      左子结点的右子结点			=		父结点   			
    

这里讨论父结点是祖父结点的左孩子,如果父结点是祖父结点的右孩子,将对称的处理方法(父结点是左孩子情况)中所有左右互换即可。

插入:利用二叉树的插入方式找到结点对应位置。首先指向根结点,如果根结点是空则插入至根结点,否则循环进行如下操作:使用key和当前结点进行判断,key小于当前结点的key时指向当前结点的左孩子,大于等于当前结点的key时指向当前结点的右孩子,如果将要指向的结点为空,则直接插入至该位置,然后进行平衡修正。

  1. 父结点是红色,叔叔结点是红色(依据性质3得出叔叔结点一定不为空,依据性质4得出祖父结点一定为黑色,父结点和插入结点打破性质4)。
    调整方案:将父结点和叔叔结点设置为黑色,将祖父结点设置为红色。使当前树黑高相对一致。
  2. 父节点是红色,叔叔结点是黑色,插入结点是父结点的右孩子(依据性质3得出叔叔结点可能为空,依据性质4得出祖父结点一定为黑色,父结点和插入结点打破性质4)。
    调整方案:将父结点作为旋转轴心,进行左旋。转换为情况3。
  3. 父结点是红色,叔叔结点是黑色,插入结点是父结点的左孩子(依据性质3得出叔叔结点可能为空,依据性质4得出祖父结点一定为黑色,父结点和插入结点打破性质4)。
    调整方案:将父结点置为黑色,祖父结点置为红色。以祖父结点为轴心,进行右旋。
    最终将根结点置为黑色。

删除:删除红黑树结点也是利用删除二叉树的方法,找到对应需要删除的点。和插入方式一致,不同的是找到key相等的结点就返回找到,找到空结点就返回没有找到。

找到的结点标记为res结点,

  • 如果res只有左子树或右子树其中的一个,就直接将wFixUp(待修正结点)标记为其拥有的子树,res标记为wDelete(待删除结点)。
  • 如果res没有左右子树,将wFixUp标记为空叶子结点(默认为黑)
  • 如果res同时有左右子树,要么找到左子树的最大结点(左子树的最右子树),要么找到右子树的最小结点(右子树的最左子树),用它的值覆盖res,颜色不覆盖,将其设置为wDelete。如果是左子树的最右子树,将wDelete的左子树设置为wFixUp,否则将wDelete的右子树设置为wFixUp。

如果wDelete是黑色,则进行如下操作。否则满足红黑树平衡性,不进行任何操作。
wFixUp结点是黑色进行调整,否则将wFixUp置为黑色。所有调整之后将根结点置为黑色。
1. 兄弟结点是红色(根据性质4得到父结点一定是黑色,左子树少了一个黑色结点,黑高改变,需要进行调整)

调整方案:将父结点置为红色,将兄弟结点置为黑色,以父结点作为轴心左旋,转换为情况2。

方案分析:

  • 兄弟结点为红色,不能减少兄弟结点子树的黑高,所以不能改变兄弟结点的颜色。
  • 不能将父结点左转到左子树,因为兄弟结点的左子树上面只能有一个黑结点,如果左转并将兄弟结点设置为黑色就会有两个黑色结点。
  • 内部无法自行调节,所以考虑进行转换,在不影响整棵树的性质情况下,将父结点设置为红色,将兄弟结点设置为黑色,以父结点为轴进行左转。
  • 得到方案2,向上依次调整。

2. 兄弟结点是黑色,兄弟结点的左右子树都是黑色(左子树少了一个黑色结点,黑高改变,需要进行调整)

调整方案:将兄弟结点设置为黑色,wFixUp结点设置为父结点,对父结点进行调整。(循环)

方案分析:

  • 子树内部没有红色结点,不能进行内部调节。
  • 因为父结点左子树减少了一个黑色结点,所以为了保持内部平衡,将兄弟结点设置为红色,减少父结点右子树黑高。
  • 因为父结点整个树整体黑高减一,所以将wFixUp设置为父结点,重复修复工作。

3. 兄弟结点是黑色,兄弟结点的左子树是红色
调整方案:将兄弟结点设置为红色,以兄弟结点为轴心进行右旋转。转换为情况4。

方案分析:

  • 如果想要实现方案4,就需要兄弟结点的左子树是黑色。所以该方案就是解决这个问题。
  • 因为兄弟结点左子树是红色,右子树是黑色,所以不能将左子树设置为黑色。兄弟结点为黑色,所以兄弟结点左子树的左子树只要接在黑色结点上就可以保持兄弟结点树自平衡。
  • 兄弟结点左子树的右子树只要保持上面有一个黑色结点即可。
  • 上面这两种情况,最好解决方案的就是保持兄弟结点是黑色。
  • 以兄弟结点为轴进行左旋,兄弟结点左子树必定是黑色。可以实现方案4。

4. 兄弟结点是黑色,兄弟结点的右子树是红色

调整方案:将兄弟结点设置为父结点的颜色,父结点设置为黑色,兄弟结点的右子树设置为黑色。以父结点为轴心进行左旋。

方案分析:

  • 兄弟结点的左子树相对平衡,只要其父结点是黑色就不会破坏其稳定性。
  • wFixUp子树缺少一个黑结点。
  • 兄弟结点的右子树相对平衡,根据性质4得出其两个子树都是黑色,所以其颜色不影响以它为根结点的树。如果左旋则需要它来取代兄弟结点的黑色。所以将其置黑。
  • 左旋之后刚好实现自平衡,在内部解决问题。

二叉树和红黑树的实现

我是按照对原理的理解,和观看相关博客、伪代码,又结合了泛型编程的方式,自己实现的二叉树和红黑树。算法流程和算法导论中的不完全一致,没有算法导论简洁。仅供参考,具体代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <sys/time.h>
using namespace std;

/* $begin binaryTree */
// 二叉树的关系特性,将二叉树特性和结点业务分离
template <typename __TYPE>
struct BinCharacter
{
    __TYPE* parent;
    __TYPE* left;
    __TYPE* right;
};

// 二叉树的结点
template <typename __KEY, typename __VALUE>
struct BinNode
{
    BinCharacter<BinNode<__KEY, __VALUE>> binCharacter;
    __KEY key;
    __VALUE value;
};

// 二叉树类
template <typename __KEY, typename __VALUE>
class BinaryTree
{
public:
    typedef BinNode<__KEY, __VALUE> BinNodeT;
    typedef BinaryTree<__KEY, __VALUE> BinaryTreeT;
    
    // 初始化为空树
    BinaryTree() noexcept
     : root(nullptr){}

    // 销毁树
    ~BinaryTree() noexcept
    {
        destroyTreeAction(root);
    }

    // 树是空
    bool 
    isEmpty() noexcept
    {

        if(root == nullptr)
            return true;
        else
            return false;
    }

    // 使用二叉排序树的方式插入结点
    bool 
    insertNode(__KEY p_key, __VALUE p_value) noexcept
    {
        // 当二叉树为空时,插入的值为头结点
        if(isEmpty())
        {
            root = createNode(p_key, p_value);
            return true;
        }

        BinNodeT* now = root;
        while(now != nullptr)
        {
            if(p_key < now->key)
            {
                // 小于,左为空则为左,不为空则向左判断
                if(now->binCharacter.left != nullptr)
                    now = now->binCharacter.left;
                else
                {
                    now->binCharacter.left = createNode(p_key, p_value);
                    now->binCharacter.left->binCharacter.parent = now;
                    return true;
                }
            }
            else
            {
                // 大于等于,右为空则为右,不为空则向右判断
                if(now->binCharacter.right != nullptr)
                    now = now->binCharacter.right;
                else
                {
                    now->binCharacter.right = createNode(p_key, p_value);
                    now->binCharacter.right->binCharacter.parent = now;
                    return true;
                }
            }
        }
        return false;
    }

    // 查找二叉树结点的value
    bool findNode(__KEY p_key, __VALUE& p_value) noexcept
    {
        BinNodeT* res = getNode(p_key);
        if(res == nullptr)return false;
        
        p_value = res->value;
        return true;
    }

    // 修改二叉树结点
    bool updateNode(__KEY p_key, __VALUE p_value) noexcept
    {
        BinNodeT* res = getNode(p_key);
        if(res == nullptr)return false;
        
        res->value = p_value;
        return true;
    }
    
    // 删除二叉树结点
    bool deleteNode(__KEY p_key) noexcept
    {
        BinNodeT* res = getNode(p_key);
        if(res == nullptr)return false;

        BinNodeT* wDelete = res;

        if(res->binCharacter.left != nullptr && 
           res->binCharacter.right != nullptr)
        {
            // 5.有左右子树,找到左边的最右结点赋值到res,并删除该结点
            wDelete = wDelete->binCharacter.left;
            while(wDelete->binCharacter.right != nullptr)
                wDelete = wDelete->binCharacter.right;

            // 如果res左子树没有右子树
            if(wDelete == res->binCharacter.left)
                res->binCharacter.left = wDelete->binCharacter.left;
            else
                wDelete->binCharacter.parent->binCharacter.right = 
                wDelete->binCharacter.left;

            res->key = wDelete->key;
            res->value = wDelete->value;
            delete wDelete;
            wDelete = nullptr;
            return true;
        }
        if(res->binCharacter.left != nullptr && 
           res->binCharacter.right == nullptr)
        {   // 3.只有左子树
            res = res->binCharacter.left;
            res->binCharacter.parent = wDelete->binCharacter.parent;
        }
        else if(res->binCharacter.left == nullptr && 
           res->binCharacter.right != nullptr)
        {   // 4.只有右子树
            res = res->binCharacter.right;
            res->binCharacter.parent = wDelete->binCharacter.parent;
        }
        else
        {   
            // 2.当前结点没有左右子树
            res = nullptr;
        }
        // 2,3,4 都需要将待删除结点的父结点进行处理
        if(wDelete != root)
            if(wDelete == wDelete->binCharacter.parent->binCharacter.left)
            {   // 待删除结点是左结点
                wDelete->binCharacter.parent->binCharacter.left = res;
            }
            else
            {   // 待删除结点是右结点
                wDelete->binCharacter.parent->binCharacter.right = res;
            }

        delete wDelete;
        wDelete = nullptr;
        return true;
    }
    
    // 销毁二叉树
    bool destroyTree() noexcept 
    {return destroyTreeAction(root);};
    // 遍历二叉树
    bool dispBinTree() noexcept 
    {return dispBinTreeAction(root);};
    // 展示二叉树结构
    bool showBinTree() noexcept 
    {return showBinTreeAction(root);};

private:
    // 得到二叉树结点
    BinNodeT* getNode(__KEY p_key) noexcept
    {
        BinNodeT* res = root;
        while(res != nullptr)
        {
            if(p_key == res->key)break;
            if(p_key < res->key) res = res->binCharacter.left;
            else res = res->binCharacter.right;
        }
        return res;
    }

    // 创建新结点
    BinNodeT* 
    createNode(__KEY p_key, __VALUE p_value) noexcept
    {
        // 创建当前结点并初始化
        BinNodeT* cur = new BinNodeT;
        cur->value = p_value;
        cur->key = p_key;
        cur->binCharacter.parent = nullptr;
        cur->binCharacter.left = nullptr;
        cur->binCharacter.right = nullptr;

        return cur;
    }
    
    // 后序遍历销毁二叉树
    bool 
    destroyTreeAction(BinNodeT* cur) noexcept
    {
        if(cur == nullptr)return false;
        destroyTreeAction(cur->binCharacter.left);
        destroyTreeAction(cur->binCharacter.right);
        delete cur;
        cur = nullptr;
        return true;
    }

    // 采用中序遍历输出顺序序列
    bool 
    dispBinTreeAction(BinNodeT* cur)
 noexcept
    {
        if(cur == nullptr)return false;
        dispBinTreeAction(cur->binCharacter.left);
        cout << endl << "key:" << cur->key << "\tvalue:" << cur->value << endl;
        dispBinTreeAction(cur->binCharacter.right);
        return true;
    }
    
    // 采用先序遍历输出二叉树结构
    bool 
    showBinTreeAction(BinNodeT* cur)
 noexcept
    {
        if(cur == nullptr)return false;
        cout << endl << "key:" << cur->key << "\tvalue:" << cur->value << endl;
        if(cur->binCharacter.parent != nullptr)
            cout << "parent key : " 
            << cur->binCharacter.parent->key << endl;
        else
            cout << "inexistence parent" << endl;
        
        if(cur->binCharacter.left != nullptr)
            cout << "left child key : " 
            << cur->binCharacter.left->key << endl;
        else
            cout << "inexistence left child" << endl;
        
        if(cur->binCharacter.right != nullptr)
            cout << "right child key : " 
            << cur->binCharacter.right->key << endl;
        else
            cout << "inexistence right child" << endl;
            
        showBinTreeAction(cur->binCharacter.left);
        showBinTreeAction(cur->binCharacter.right);
        
        return true;
    }

    BinNodeT* root;
};

/* $end binaryTree */




/* $begin rbTree */
/*
    红黑树5条基本性质
    (1)每个结点或者是黑色,或者是红色。
    (2)根结点是黑色。
    (3)每个叶子结点是黑色。(为空的叶子结点)
    (4)如果一个结点是红色的,则它的子结点必须是黑色的。
    (5)从一个结点到该结点的子孙结点的所有路径上包含相同数目的黑结点。
*/

#define BLACK 0 // 黑
#define RED 1   // 红

// 红黑树的结点
template <typename __KEY, typename __VALUE>
struct RBNode
{
    BinCharacter<RBNode<__KEY, __VALUE>> binCharacter;
    bool color;
    __KEY key;
    __VALUE value;
};

// 红黑树类
template <typename __KEY, typename __VALUE>
class RBTree
{
public:
    typedef RBNode<__KEY, __VALUE> RBNodeT;
    typedef RBTree<__KEY, __VALUE> RBTreeT;
    
    // 初始化为空树
    RBTree() noexcept
     : nil(new RBNodeT)
    {
        nil->color = BLACK;        
        nil->binCharacter.left = nil;
        nil->binCharacter.right = nil;
        nil->binCharacter.parent = nil;        
        root = nil;
    }

    // 销毁树
    ~RBTree() noexcept
    {
        destroyTreeAction(root);
        delete nil;
        nil = nullptr;
    }

    // 树是空
    bool 
    isEmpty() noexcept
    {

        if(root == nil)
            return true;
        else
            return false;
    }

    // 插入结点
    bool 
    insertNode(__KEY p_key, __VALUE p_value) noexcept
    {
        // 当红黑树为空时,插入的值为头结点
        if(isEmpty())
        {
            root = createNode(p_key, p_value);
            setNodeRed(root);
            insertNodeFixUp(root);
            return true;
        }

        RBNodeT* now = root;
        while(now != nil)
        {
            if(p_key < now->key)
            {
                // 小于,左为空则为左,不为空则向左判断
                if(now->binCharacter.left != nil)
                    now = now->binCharacter.left;
                else
                {
                    now->binCharacter.left = createNode(p_key, p_value);
                    now->binCharacter.left->binCharacter.parent = now;
                    setNodeRed(now->binCharacter.left);
                    insertNodeFixUp(now->binCharacter.left);
                    return true;
                }
            }
            else
            {
                // 大于等于,右为空则为右,不为空则向右判断
                if(now->binCharacter.right != nil)
                    now = now->binCharacter.right;
                else
                {
                    now->binCharacter.right = createNode(p_key, p_value);
                    now->binCharacter.right->binCharacter.parent = now;
                    setNodeRed(now->binCharacter.right);
                    insertNodeFixUp(now->binCharacter.right);
                    return true;
                }
            }
        }
        return false;
    }

    // 查找红黑树结点的value
    bool 
    findNode(__KEY p_key, __VALUE& p_value) noexcept
    {
        RBNodeT* res = getNode(p_key);
        if(res == nil)return false;
        
        p_value = res->value;
        return true;
    }

    // 修改红黑树结点
    bool updateNode(__KEY p_key, __VALUE p_value) noexcept
    {
        RBNodeT* res = getNode(p_key);
        if(res == nil)return false;
        
        res->value = p_value;
        return true;
    }
    
    // 删除红黑树结点
    bool 
    deleteNode(__KEY p_key) noexcept
    {
        RBNodeT* res = getNode(p_key); // 逻辑上需要删除的结点
        if(res == nil)return false;

        RBNodeT* wDelete = res, *wFixUp = nil;
        nil->binCharacter.parent = nil;

        if(res->binCharacter.left != nil && 
           res->binCharacter.right != nil)
        {
            // 5.有左右子树,找到左边的最右结点赋值到res,并删除该结点
            wDelete = wDelete->binCharacter.left;
            while(wDelete->binCharacter.right != nil)
                wDelete = wDelete->binCharacter.right;

            wFixUp = wDelete->binCharacter.left;
            wFixUp->binCharacter.parent = wDelete->binCharacter.parent;

            // 如果res左子树没有右子树
            if(wDelete == res->binCharacter.left)
                res->binCharacter.left = wFixUp;
            else
                wDelete->binCharacter.parent->binCharacter.right = 
                wFixUp;
            res->key = wDelete->key;
            res->value = wDelete->value;
        }
        else
        {
            if(res->binCharacter.left != nil && 
               res->binCharacter.right == nil)
            {   // 3.只有左子树
                res = res->binCharacter.left;
                res->binCharacter.parent = wDelete->binCharacter.parent;
            }
            else if(res->binCharacter.left == nil && 
               res->binCharacter.right != nil)
            {   // 4.只有右子树
                res = res->binCharacter.right;
                res->binCharacter.parent = wDelete->binCharacter.parent;
            }
            else
            {   
                // 2.当前结点没有左右子树
                res = nil;
            }
            // 2,3,4 都需要将待删除结点的父结点进行处理
            if(wDelete != root)
                if(wDelete == wDelete->binCharacter.parent->binCharacter.left)
                {   // 待删除结点是左结点
                    wDelete->binCharacter.parent->binCharacter.left = res;
                }
                else
                {   // 待删除结点是右结点
                    wDelete->binCharacter.parent->binCharacter.right = res;
                }
            wFixUp = res;
        }

        if(isBlack(wDelete))
            deleteNodeFixUp(wFixUp);

        if(wDelete == root)root = res;
        delete wDelete;
        wDelete = nullptr;
        return true;
    }
    
    // 销毁红黑树
    bool 
    destroyTree() noexcept 
    {return destroyTreeAction(root);};
    // 遍历红黑树
    bool 
    dispBinTree() noexcept 
    {return dispBinTreeAction(root);};
    // 展示红黑树结构
    bool 
    showBinTree() noexcept 
    {return showBinTreeAction(root);};

 private:
    // 得到红黑树结点
    RBNodeT* getNode(__KEY p_key) noexcept
    {
        RBNodeT* res = root;
        while(res != nil)
        {
            if(p_key == res->key)break;
            if(p_key < res->key) res = res->binCharacter.left;
            else res = res->binCharacter.right;
        }
        return res;
    }

    // 创建新结点
    RBNodeT* 
    createNode(__KEY p_key, __VALUE p_value) noexcept
    {
        // 创建当前结点并初始化
        RBNodeT* cur = new RBNodeT;
        cur->value = p_value;
        cur->key = p_key;
        cur->binCharacter.parent = nil;
        cur->binCharacter.left = nil;
        cur->binCharacter.right = nil;

        return cur;
    }

    // 将树以cur为轴心左旋
    void 
    leftRotate(RBNodeT* cur) noexcept
    {
        RBNodeT* x = cur, *y = cur->binCharacter.right,
            *parent = cur->binCharacter.parent;

        // 如果为头结点
        if(parent == nil)
        {
            root = y;
            y->binCharacter.parent = nil;
        }
        else
        {
            // 将y置为轴心
            if(x == parent->binCharacter.left)
            {   // 如果为左子树
                parent->binCharacter.left = y; 
            }
            else
            {   // 如果为右子树
                parent->binCharacter.right = y;
            }
            y->binCharacter.parent = parent;

        }

        // 将y的左子树置为x的右子树
        x->binCharacter.right = y->binCharacter.left;
        if(y->binCharacter.left != nil)
            y->binCharacter.left->binCharacter.parent = x;

        // 将x置为y的左子树
        y->binCharacter.left = x;
        x->binCharacter.parent = y;

        nil->binCharacter.parent = nil;
        nil->binCharacter.left = nil;
        nil->binCharacter.right = nil;
    }

    // 将树以cur为轴心右旋
    void 
    rightRotate(RBNodeT* cur) noexcept
    {
        RBNodeT* y = cur, *x = cur->binCharacter.left,
            *parent = cur->binCharacter.parent;

        // 如果为头结点
        if(parent == nil)
        {
            root = y;
            y->binCharacter.parent = nil;
        }
        else            
        {
            // 将x置为轴心
            if(y == parent->binCharacter.left)
            {   // 如果为左子树
                parent->binCharacter.left = x; 
            }
            else
            {   // 如果为右子树
                parent->binCharacter.right = x;
            }
            x->binCharacter.parent = parent;
        }

        // 将x的右子树置为y的左子树
        y->binCharacter.left = x->binCharacter.right;
        if(x->binCharacter.right != nil)
            x->binCharacter.right->binCharacter.parent = y;

        // 将y置为x的右子树
        x->binCharacter.right = y;
        y->binCharacter.parent = x;

        nil->binCharacter.parent = nil;
        nil->binCharacter.left = nil;
        nil->binCharacter.right = nil;
    }

    bool 
    setNodeRed(RBNodeT* cur) noexcept
    {
        if(cur == nil)return false;
        cur->color = RED;
        return true;
    }

    bool 
    setNodeBlack(RBNodeT* cur) noexcept
    {
        if(cur == nil)return false;
        cur->color = BLACK;
        return true;
    }

    bool 
    isRed(RBNodeT* cur) noexcept
    {
        if(cur->color == RED)return true;
        return false;
    }

    bool 
    isBlack(RBNodeT* cur) noexcept
    {
        if(cur->color == BLACK)return true;
        return false;
    }

    // 插入修正
    bool 
    insertNodeFixUp(RBNodeT* cur) noexcept
    {
        RBNodeT* z = cur;
        // 如果父结点是红色则修正
        while(isRed(cur->binCharacter.parent))
        {

            // 如果父结点是红色,就一定有祖父结点
            RBNodeT* grandPa = cur->binCharacter.parent->binCharacter.parent;
            
            if(grandPa->binCharacter.left == z->binCharacter.parent)
            {// 父结点是左孩子
                if(isRed(grandPa->binCharacter.right))

                {// 叔结点是红色

                    // 将父结点和叔结点置为黑色,祖父结点置为红色
                    setNodeBlack(grandPa->binCharacter.left);
                    setNodeBlack(grandPa->binCharacter.right);
                    setNodeRed(grandPa);
                    // 将当前结点指向祖父结点
                    z = grandPa;
                }
                else
                {// 叔结点是黑色
                    // 如果当前结点是右结点,则以父结点为轴左旋
                    if(z == z->binCharacter.parent->binCharacter.right)
                    {
                        z = z->binCharacter.parent;
                        leftRotate(z);
                    }
                    
                    setNodeBlack(z->binCharacter.parent);
                    setNodeRed(grandPa);
                    rightRotate(grandPa);
                }
            }
            else
            {// 父结点是右孩子
                if(isRed(grandPa->binCharacter.left))

                {// 叔结点是红色

                    // 将父结点和叔结点置为黑色,祖父结点置为红色
                    setNodeBlack(grandPa->binCharacter.left);
                    setNodeBlack(grandPa->binCharacter.right);
                    setNodeRed(grandPa);
                    // 将当前结点指向祖父结点
                    z = grandPa;
                }
                else
                {// 叔结点是黑色
                    // 如果当前结点是左结点,则以父结点为轴右旋
                    if(z == z->binCharacter.parent->binCharacter.left)
                    {
                        z = z->binCharacter.parent;
                        rightRotate(z);
                    }
                    
                    setNodeBlack(z->binCharacter.parent);
                    setNodeRed(grandPa);
                    leftRotate(grandPa);
                }
            }
        }

        setNodeBlack(root);
        return true;
    }

    // 删除红黑树结点修正
    bool 
    deleteNodeFixUp(RBNodeT* cur) noexcept
    {
        RBNodeT* brother = nil;

        while(cur->binCharacter.parent != nil && isBlack(cur))
        {
            if(cur == cur->binCharacter.parent->binCharacter.left)
            {// 当前结点是左孩子
                brother = cur->binCharacter.parent->binCharacter.right;

                if(isRed(brother))
                {// 1.兄弟结点是红色,将父结点左旋,转换为情况2
                    setNodeRed(cur->binCharacter.parent);
                    setNodeBlack(brother);
                    leftRotate(cur->binCharacter.parent);
                    brother = cur->binCharacter.parent->binCharacter.right;
                }

                // 兄弟结点为黑
                if(isBlack(brother->binCharacter.left) &&
                   isBlack(brother->binCharacter.right))
                {// 2.兄弟结点的左右子树都为黑,将兄弟结点置为红,以父结点继续修正
                    setNodeRed(brother);
                    cur = cur->binCharacter.parent;
                }
                else
                {// 兄弟结点的子结点有一个是红色
                    if(isRed(brother->binCharacter.left))
                    {// 3.兄弟结点的左子树是红色,将兄弟结点置为红色,
                     // 以兄弟结点为轴进行右旋转
                        setNodeRed(brother);
                        rightRotate(brother);
                    }

                    // 4.兄弟结点的右子树是红色,设置父结点为黑色,
                    // 兄弟结点的右孩子为黑色,以父结点为轴心左旋
                    brother->color = cur->binCharacter.parent->color;
                    setNodeBlack(cur->binCharacter.parent);
                    setNodeBlack(brother->binCharacter.right);
                    leftRotate(cur->binCharacter.parent);

                    cur = root;
                }
            }
            else
            {// 当前结点是右孩子

                brother = cur->binCharacter.parent->binCharacter.left;

                if(isRed(brother))
                {// 1.兄弟结点是红色,将父结点右旋,转换为情况2
                    setNodeRed(cur->binCharacter.parent);
                    setNodeBlack(brother);
                    rightRotate(cur->binCharacter.parent);
                    brother = cur->binCharacter.parent->binCharacter.left;
                }

                // 兄弟结点为黑
                if(isBlack(brother->binCharacter.left) &&
                   isBlack(brother->binCharacter.right))
                {// 2.兄弟结点的左右子树都为黑,将兄弟结点置为红,以父结点继续修正
                    setNodeRed(brother);
                    cur = cur->binCharacter.parent;
                }
                else
                {// 兄弟结点的子结点有一个是红色
                    if(isRed(brother->binCharacter.right))
                    {// 3.兄弟结点的右子树是红色,将兄弟结点置为红色,
                     // 以兄弟结点为轴进行左旋转
                        setNodeRed(brother);
                        leftRotate(brother);
                    }

                    // 4.兄弟结点的左子树是红色,设置父结点为黑色,
                    // 兄弟结点的左孩子为黑色,以父结点为轴心右旋
                    brother->color = cur->binCharacter.parent->color;
                    setNodeBlack(cur->binCharacter.parent);
                    setNodeBlack(brother->binCharacter.left);
                    rightRotate(cur->binCharacter.parent);

                    cur = root;
                }
            }
        }
        setNodeBlack(cur);
        return true;
    }
    
    // 后序遍历销毁红黑树
    bool 
    destroyTreeAction(RBNodeT* cur) noexcept
    {
        if(cur == nil)return false;
        destroyTreeAction(cur->binCharacter.left);
        destroyTreeAction(cur->binCharacter.right);
        delete cur;
        cur = nullptr;
        return true;
    }

    // 采用中序遍历输出顺序序列
    bool 
    dispBinTreeAction(RBNodeT* cur)
 noexcept
    {
        if(cur == nil)return false;
        dispBinTreeAction(cur->binCharacter.left);
        
        cout << endl << "key:" << cur->key 
             << "\tvalue:" << cur->value 
             << "\tcolor:";
        if(isRed(cur))cout << "red" << endl;
        else cout << "black" << endl;
            
        dispBinTreeAction(cur->binCharacter.right);
        return true;
    }
    
    // 采用先序遍历输出红黑树结构
    bool 
    showBinTreeAction(RBNodeT* cur)
 noexcept
    {
        if(cur == nil)return false;
        
        cout << endl << "key:" << cur->key 
             << "\tvalue:" << cur->value 
             << "\tcolor:";
        if(isRed(cur)) cout << "red" << endl;
        else cout << "black" << endl;

        if(cur->binCharacter.parent != nil)
            cout << "parent key : " 
            << cur->binCharacter.parent->key << endl;
        else
            cout << "inexistence parent" << endl;
        
        if(cur->binCharacter.left != nil)
            cout << "left child key : " 
            << cur->binCharacter.left->key << endl;
        else
            cout << "inexistence left child" << endl;
        
        if(cur->binCharacter.right != nil)
            cout << "right child key : " 
            << cur->binCharacter.right->key << endl;
        else
            cout << "inexistence right child" << endl;
            
        showBinTreeAction(cur->binCharacter.left);
        showBinTreeAction(cur->binCharacter.right);
        
        return true;
    }

    RBNodeT* root;
    RBNodeT* nil;
};



/* $end rbTree */

template <typename TreeT>
void test(TreeT& t)
{
    while(1)
    {
        int op = 0;
        int key;
        cout << endl << "cin operator(1.insert 2.delete) : ";
        cin >> op;
        if(op == 1)
        {
            cout << "insert key: ";
            cin >> key;
            t.insertNode(key, key);

            t.dispBinTree();
            t.showBinTree();
        }
        else if(op == 2)
        { 
            cout << "delete key : ";
            cin >> key;
            t.deleteNode(key);

            t.dispBinTree();
            t.showBinTree();
        }
        
    }
}

int main(int argc, char **argv)
{
    RBTree<int, int> t;
//  测试二叉树
//  BinaryTree<int, int> bt;
//  test(bt);
/*
    t.insertNode(5, 5);
    t.insertNode(4, 4);
    t.insertNode(2, 2);
    t.insertNode(3, 3);
    t.insertNode(7, 7);
    t.insertNode(6, 6);
    t.insertNode(8, 8);

    t.dispBinTree();
    t.showBinTree();
    */
    test(t);
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殇弑天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值