您的位置:首页 > 新闻 > 热点要闻 > 广告网站建设公司_移动商城app下载_网络营销师培训费用是多少_小红书推广怎么做

广告网站建设公司_移动商城app下载_网络营销师培训费用是多少_小红书推广怎么做

2025/5/22 18:28:57 来源:https://blog.csdn.net/2301_81857941/article/details/142884602  浏览:    关键词:广告网站建设公司_移动商城app下载_网络营销师培训费用是多少_小红书推广怎么做
广告网站建设公司_移动商城app下载_网络营销师培训费用是多少_小红书推广怎么做

1.红黑树的概念 

红黑树是一颗二叉搜索树,他的每一个结点增加一个存储位来表示结点的颜色,可以是红色或者黑色,其中会有四条规则对红黑树进行约束,以下我将一一介绍.

    1.1 红黑树的规则:

1.每个结点不是红色就是黑色

2.根结点是黑色的

3.如果一个结点是红色的,则它的两个孩子结点必须是黑色的,也就是说任意的一条路径不会有连续的红色结点。

4.对于任意一个结点,从该结点到其所有NULL结点的简单路径上,均包含相同数量的黑色结点

以下的图为一个标准的红黑树:

   1.2  如何确保红黑树满足规则4?

1.由规则4可知各个路径要有相同的黑色结点数量,所以在极端的情况下,最短的路径可以全是黑色结点,假设这个路径的黑色结点为bh(black height)

2.由规则2和3可知,任意一条路径不会有连续的红色结点出现,所以是红色和黑色结点交替出现,此时最长的路径的高度为2*bh.

3.综合红黑树的4条规则可以知道,一个正常的红黑树任意一条路径的高度h,满足bh<=h<=2*bh

    1.3 红黑树的效率

 假设N是红黑树中结点的数量,h是最短路径的长度,,由此推出h约等于logN,那么时间复杂度还是O(logN)。

2.红黑树的实现 

    2.1 红黑树的结构

enum Colour

{
     RED,

     BLACK

};

template<class K,class V>

struct RBTreeNode

{

     pair<K,V>_kv;   

     RBTreeNode<K, V>* _left;
     RBTreeNode<K, V>* _right;
     RBTreeNode<K, V>* _parent;
     Colour _col;
   
     
    RBTreeNode(const pair<K, V>& kv)
     :_kv(kv)
      , _left(nullptr)
      , _right(nullptr)
      , _parent(nullptr)
     {}
 }; 
 
template<class K,class V>
class RBTree
{
    typedef RBTreeNode<K,V> Node;
 public:
private:
           Node*_root = nullptr;
};

  2.2 红黑树的插入

2.2.1 红黑树插入一个值的大概过程

1.插入一个值按二叉搜索树规则进行插入,插入后我们只需要观察是否符合红黑树的4条规则。

2.如果是空树插入,新增结点是黑色结点。如果是非空树插入,新增结点必须为红色结点,因为如果插入的是黑色结点会破坏规则4。

3.如果插入的父亲结点为黑色结点就没有违反任何规则,插入就会结束。

4.如果插入的父亲结点为红色的,则违反规则3,要进一步变化,在这里先把新增的结点叫做cur(缩写为c),c的父亲结点为parent(缩写为p),p的父亲标识为grandfather(缩写为g),p的兄弟叫做uncle(缩写为u)。

2.2.2    情况1:变色

c为红,p为红,g为黑,u存在且为红,则将p和u变黑,g变红,再把g当做新的c,继续往上更新。(这样既不会有两个连续的红色结点,也能让两个路径的黑色结点数量相等,从而满足规则4)

如下图所示:

红黑树跟前面我发布的C++之AVL树类似有,还有很多情况,这里就不一一介绍,按照上述的思维即可理解:

 

 2.2.3 情况2:单旋+变色

c为红,p为红,g为黑,u不存在或者u存在且为黑,u不存在,则c一定是新增结点,u存在且为黑,则c一定不是新增,c之前是黑色的,是在c的子树中插入,符合情况1,变色将c从黑色变成红色,更新上来的。(关于是否为新增结点要根据路径黑色结点数量来判断)

分析:

p必须变黑才能解决两个红色结点连续的问题,u不存在或者是黑色,在p变成黑色,g变成红色后都无法满足红黑树的规则,所以这里除了变色还需要旋转。旋转在上篇文章:C++之AVL树已经介绍过了,这里的旋转跟AVL树的旋转类似。

这里分为两种情况:
1. 

如果p是g的左,c是p的左,那么以g为旋转点进行右单旋再把p变黑,g变红即可。

2.

如果p是g的右,c是p的右,那么g为旋转点进行左单旋,再把p变黑,g变红即可。

 

2.2.4   情况3:双旋+变色 

c为红,p为红,g为黑,u不存在或者u存在且为黑,u不存在,则c一定是新增结点,u存在且为黑,则c一定不是新增,c之前是黑色的,是在c的子树中插入,符合情况1,变色将c从黑色变成红色,更新上来的。

这里的双旋和变色又可以分为两种情况:

情况1:

如果p是g的左,c是p的右,那么先以p为旋转点进行左单旋,再以g为旋转点进行右单旋,再把c变黑,g变红即可。 

情况2:

 如果p是g的右,c是p的左,那么先以p为旋转带你进行右单旋,再以g为旋转点进行左单旋,再把c变黑,g变红即可。

2.3 红黑树的插入代码实现

bool Insert(const pair<K,V>&kv)

{

      if(_root == nullptr)

      {

           _root = new Node(kv);

           _root->_col = BLACK;

           return true;

       }

     

   Node*parent = nullptr;

   Node*cur = _root

   while(cur)

   {

            if(cur->_kv.first<kv.first)

             {
                  parent = cur;

                  cur = cur->_right;

             }

             else if(cur->_kv.first >kv.first)

            {

                    parent = cur;

                    cur = cur->_left;

            }

            else

           {

                   return false;

           }

   }

    cur = new Node(kv);

    cur ->_col = RED;

   if(parent->_kv.first < kv.first)

   {
        parent->_right = cur;

   }

   else if(parent->_kv.first<kv.first)

   {

       parent->_left = cur;

   }

   cur->_parent = parent;

  while(parent&&parent->_col == RED)

  {

       Node*grandparent = parent->_parent;

       if(parent == grandfather->_left)

   {
        Node*uncle = grandfather->_right;

        if(uncle && uncle->_col == RED)

        {

            // u存在且为红-》变色再继续

              parent->_col = uncle->_col = BLACK;

              grandfather->_col = RED;

          

              cur = grandfather;

              parent = cur->_parent;

       }

  }

else 

{

    // u存在且为黑或不存在-》旋转+变色

          if(cur == parent->_left)

          {

                RotateR(grandfather);    

                parent->_col = BLACK ;
                grandfather->_col = RED;
          }
        
       else
    {
    //双旋
    RotateL(parent);
    RotateR(grandfather);
     cur->_col = BLACK;
     grandfather->_col = RED;
       }
               break;
      }
}
else
{            
         Node*uncle = grandfather->_left;
// 叔叔存在且为红, - 》变⾊即可
         if(uncle && uncle->_col == RED)
if (uncle && uncle->_col == RED)
{
   parent->_col = uncle->_col = BLACK;
    grandfather->_col = RED;
   
  
  // 继续往上处理
   cur = grandfather;
   parent = cur->_parent;
}
  else // 叔叔不存在,或者存在且为⿊
{
// 情况⼆:叔叔不存在或者存在且为⿊
// 旋转 + 变⾊
// g
// u p
// c
    if (cur == parent->_right)
{
     RotateL (grandfather);
     parent->_col = BLACK;
     grandfather->_col = RED;
}
else
{
// g
// u p
// c
   RotateR (parent);
   RotateL (grandfather);
   cur->_col = BLACK;
grandfather->_col = RED;
     }
   break ;
     }
  }
}
_root->_col = BLACK;
return true ;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com