红黑树学习笔记

前言

map/set/multiset/multimap的底层是二叉搜索树,而二叉搜索树也会出现一个单链表的情况,所以通过增加平衡因子来降低树的高度,这也是AVL树的实现原理,在AVL树那里有个疑惑就是不一定有平衡因子也能调节,在学习了红黑树的实现后,这个疑问的答案大概就是这个了,所以对此进行记录,以防遗忘。

关于红黑树的代码和笔记

红黑树的是给每个结点增加了颜色Red和Black,通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路径会比其他路径长出俩倍,达到这样的接近平衡的状态。

特点有:1、root结点是黑的.

2、某个结点是红的话,如果它有子节点,那么子节点是黑的

3、对于某个结点而言,其以及子节点的路径里含有黑色节点的个数是相同的。

4.空节点默认是黑的。

enum Color
{
    black,
    red
}
template<class K,class V>
struct RedBlackTreeNode
{
    RedBlackTreeNode<K,V>* _left;
    RedBlackTreeNode<K,V>* _right;
    RedBlackTreeNode<K,V>* _parent;
    pair<K,V> _kv;
    Color _color;
    
    RedBlackTreeNode(const pair<K,V>& kv)
    :_left(nullptr),
     _right(nullptr),
     _parent(nullptr),
     _kv(kv),
     _color(red)//默认红色后面好调整
    {};
};

检测插入节点后,红黑树性质是否被破坏

插入默认是红色节点,如果父辈结点是黑色的,就不需要做出改变,但如果是红的,就需要进行讨论了,这里讨论不只是包含插入的情况。

1、当前的为红,父节点为红,叔叔节点为红,祖父节点为黑

 

 

这里的解决方案就是将parent、uncle节点变黑,grandpa节点变红,如果这只是某个子树的部分,cur就要指代目前的grandpa,再根据情况向上进行调整 。

后面的情况基本上属于这个的变种,代码表示这种情况:

while(parent&&parent->_color==red)
{
    Node* grandparent =parent->_parent;//这里的Node 是typedef的,也就是RedBlackTreeNode<K,V>
    if(grandparent->_left==parent)
    {
        Node* uncle=grandparent->_right;
        //uncle 存在且为红
        if(uncle&&uncle->_color==red)
        {
            parent->_color=black;
            uncle->_color=black;
            grandparent->_color=red;
            //向上调整
            cur=grandparent;
            parent=cur->_parent;
        }    
     }   
}

2、当前的为红,父节点为红,祖父节点为黑,叔叔节点不存在

如果叔叔节点不存在,那么当前的红色节点必然是新插入的节点,不然父节点和当前节点必然有一个是黑的,不然不符合红色节点的字节点是黑,以及每条简单路径下黑色节点个数相同。

变换之后成为了 

 

如果这只是某个子树的部分,cur就要指代目前的parent,再根据情况向上进行调整 。

3、当前的为红,父节点为红,祖父节点为黑,叔叔节点存在

这种情况当前的节点肯定不是插入的节点,而是先前是黑色调整之后变换成红色的,而且这里的叔叔节点也肯定是黑色,这样才符合要求,所以这里就要再次调整。

这里的情况进行右旋,再变色,如果在右边就左旋再变色,视情况而定:

A:

 

 

 

这里是直接右旋并变色。 

B: 

 

这里就变成了A的情况了 ,也就是先左旋再右旋。

还有其他的 情况,但本质上和上面的情况都大差不差,按照上面的逻辑进行变换就行了。

针对举例的情况进行代码表示:

while(parent&&parent->_color==red)
{
    Node* grandparent =parent->_parent;//这里的Node 是typedef的,也就是            
                                       //RedBlackTreeNode<K,V>
    if(grandparent->_left==parent)
    {
        Node* uncle=grandparent->_right;
        //uncle 存在且为红
        if(uncle&&uncle->_color==red)
        {
            parent->_color=black;
            uncle->_color=black;
            grandparent->_color=red;
            //向上调整
            cur=grandparent;
            parent=cur->_parent;
        }  
        else//uncle不存在|uncle存在且为黑
        {
            //     g
            //   p   u
            //cur
            if(cur==parent->_left)
            {
                rightRotation(grandparent);//这个方法的实现是在AVL树那篇里提到的
                                          //这里了解思路即可
                parent->_left=black;
                grandparent->_color=red;
            }
            else
            {
                //     g
                // p       u
                //  cur
                leftRotation(parent);
                rightRotation(grandparent);
                cur->_color =black;
                parent->_color=red;
                grandparent->_color=red;
            }
            break;
        }  
     }  
     else //grandparent->_right==parent
     {
        Node* uncle=grandparent->_left;
        //uncle 存在且为红
        if(uncle&&uncle->_color==red)
        {
            parent->_color=black;
            uncle->_color=black;
            grandparent->_color=red;
            //向上调整
            cur=grandparent;
            parent=cur->_parent;
        }  
        else
        {
            //     g
            //  u      p
            //            cur
            if(cur==parent->_right)
            {
                leftRotation(grandparent);
                grandparent->_color=red;
                parent->_color=black;
                
            }
            else
            {
                //      g
                //  u        p
                //        cur
                rightRotation(parent);
                leftRotation(grandparent);
                cur->_color=black;
                grandparent->_color=red;
            }
            break;
        }
     }
}

 

 

 

 

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值