• 平衡搜索树(二) Rb 红黑树


    Rb树简介

    红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单 路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。(性质3、性质4保证了红黑树最长的路径不超过最短路径的两倍

    如图所示:


    红黑树是满足下面红黑性质的二叉搜索树


    1. 每个节点,不是红色就是黑色的

    2. 根节点是黑色的

    3. 如果一个节点是红色的,则它的两个子节点是黑色的

    4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

    好,现在了解了红黑树的特性之后,我们来开始创建红黑树。

    //红黑树的节点的结构
     1 template<class K,class V>         
     2 struct RedBlaceTreeNode
     3 {
     4     typedef RedBlaceTreeNode<K, V> Node;
     5     RedBlaceTreeNode(const K& key,const V& value)
     6         :_left(NULL), _right(NULL), _parent(NULL)
     7         , _key(key), _value(value), _col(RED)
     8     {}
     9 
    10     Node* _left;
    11     Node* _right;
    12     Node* _parent;
    13     K _key;
    14     V _value;
    15     Sign _col;
    16 };

    //红黑树的结构

    template<class K,class V>
    class RedBlaceTree
    {
        typedef RedBlaceTreeNode<K, V> Node;
    public:
        RedBlaceTree()
            :_root(NULL)
        {}
    public:
        bool _Push(const K& key, const V& value);
        void _LeftSpin(Node*& parent);
        void _RightSpin(Node*& parent);
        void _LeftRightSpin(Node*& parent);
        void _RightLeftSpin(Node*& parent);
    
        /*Check*/
        //1. 每个节点,不是红色就是黑色的
        //2. 根节点是黑色的
        //3. 如果一个节点是红色的,则它的两个子节点是黑色的
        //4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
        void _Inorder(){ Inorder(_root); }
        void Inorder(Node* root);
    protected:
        Node* _root;
    };

    //创建红黑树的函数 _Push()

    插入的几种情况

    cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

    1.第一种情况 cur为红,p为红,g为黑,u存在且为红 则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。( 还挺简单  O(∩_∩)O   继续往下看↓↓)

    2.第二种情况 cur为红,p为红,g为黑,u不存在/u为黑 p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转 p、g变色--p变黑,g变红

    3.第三种情况 cur为红,p为红,g为黑,u不存在/u为黑
    p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转 则转换成了情况2

    template<class K, class V>
    bool RedBlaceTree<K, V>::_Push(const K& key, const V& value)
    {
        Node* cur = _root;
        Node* parent = NULL;
        if (_root == NULL)
        {
            _root = new Node(key, value);
            _root->_col = BLACK;
        }
        else
        {
            while (cur)
            {
                parent = cur;
                if (key > cur->_key)
                {
                    cur = cur->_right;
                }
                else if (key < cur->_key)
                {
                    cur = cur->_left;
                }
                else
                {
                    return false;
                }
            }
            cur = new Node(key, value);
            if (key > parent->_key)
            {
                parent->_right = cur;
                cur->_parent = parent;
            }
            else
            {
                parent->_left = cur;
                cur->_parent = parent;
            }
    
            if (parent->_col == RED)     //如果父亲节点为红色就需要调整
            {
                bool sign = false;      //标记位,用来标记grandparent是否为根节点
                while (cur->_parent)
                {
                    Node* grandparent = NULL;
                    Node* uncle = NULL;
                    parent = cur->_parent;
                    grandparent = parent->_parent;
    
                    if (grandparent)       //如果祖父节点存在
                    {
                        if (grandparent == _root)
                        {
                            sign = true;    //标记祖父节点是否为根节点
                        }
    
                        if (parent->_key > grandparent->_key)   //确定叔父节点
                        {
                            uncle = grandparent->_left;
                        }
                        else
                        {
                            uncle = grandparent->_right;
                        }
    
    
                        //第一种情况:cur为红,p为红,g为黑,u存在且为红 
                        if (uncle && uncle->_col == RED)
                        {
                            parent->_col = BLACK;
                            uncle->_col = BLACK;
                            grandparent->_col = RED;
                            if (sign)
                            {
                                break;
                            }
                            cur = grandparent;
                        }
    
                        //第二种情况:cur为红,p为红,g为黑,u不存在/u为黑(单旋)
                        //第三种情况:cur为红,p为红,g为黑,u不存在/u为黑(双旋)
                        else
                        {
                            //第二
                            if (grandparent->_left == parent && parent->_left == cur)
                            {
                                grandparent->_col = RED;
                                parent->_col = BLACK;
                                _RightSpin(grandparent);
                                if (sign)
                                {
                                    _root = grandparent;
                                }
                                break;
                            }
                            else if (grandparent->_right == parent && parent->_right == cur)
                            {
                                grandparent->_col = RED;
                                parent->_col = BLACK;
                                _LeftSpin(grandparent);
                                if (sign)
                                {
                                    _root = grandparent;
                                }
                                break;
                            }
                            //第三
                            else if (grandparent->_left == parent && parent->_right == cur)
                            {
                                grandparent->_col = RED;
                                cur->_col = BLACK;
                                _LeftRightSpin(grandparent);
                                if (sign)
                                {
                                    _root = grandparent;
                                }
                                break;
                            }
                            else if (grandparent->_right == parent && parent->_left == cur)
                            {
                                grandparent->_col = RED;
                                cur->_col = BLACK;
                                _RightLeftSpin(grandparent);
                                if (sign)
                                {
                                    _root = grandparent;
                                }
                                break;
                            }
                        }
                    }
                    else   //cur 的上面只有一层
                    {
                        break;
                    }
                }
            }
        }
        _root->_col = BLACK;
    }
  • 相关阅读:
    labview 中的一些简写全称
    socket
    putty
    在波形图表中显示多条曲线
    简单的通电延时触发电路
    Linux sed 批量替换多个文件中的字符串
    PhpMyAdmin管理,登录多台远程MySQL服务器
    MySQL客户端工具推荐
    Redis的几个认识误区
    Redis 的 5 个常见使用场景
  • 原文地址:https://www.cnblogs.com/shihaokiss/p/5440999.html
Copyright © 2020-2023  润新知