红黑树(RedblackTree)上--增加节点

本文介绍了红黑树的基本概念,包括其作为二叉搜索树的特性,节点颜色规则等。详细阐述了新节点插入过程,并通过实例展示了插入后如何进行平衡调整。同时提供了红黑树增加节点的代码实现,探讨了代码优化策略,帮助读者深入理解红黑树的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么事RBtree:

所谓的红黑树它需要满足一下条件:
1、该树是一颗二叉搜索树(搜索树就是按照节点值大小进行排序插入,中序就是所有节点的从小到大排序)
2、每个节点不是红色就是黑色
3、根节点为黑色
4、红节点不相连
5、任一节点至NULL(树尾)的任何途径,所含之黑节点树必须相同
为了统一,我们视NULL为黑节点。

红黑树的有点就在于它没有平衡因子,唯一需要让它调整的就是新节点的颜色,在数据插入上大大减少了调整次数。
我们来简单的看一组数据组成的个红黑树的模型:
{100,80,60,40,50,75,73,72,74}
这里写图片描述
新节点的颜色我们设为红色,我们把新的节
这里写图片描述
这里写图片描述
上图是模型红黑树调整的全过程,蓝色箭头代表的是平衡的红黑树有的是新节点的插入,红箭头代表对新插入节点导致不平衡的调整平衡过程。

二、RBTree是怎么实现的:

树的操作再前面刚开始学二叉树的时候相信你已经有所掌握,bst、avl、rbt树都一样,这三中树最重要的操作就是增加节点和删除节点,在这里我也只对节点的增加进行代码分析,在红黑树下篇会对其节点的删除代码进行分析,下面就是RBtree的增加节点代码展示:

#pragma once

template<class Type>
 class RBTree;
typedef enum{RED = 0, BLACK = 1}COLOR;
template<class Type>
class RBNode
{
    friend class RBTree<Type>;
public:
    RBNode():data(Type()),leftchild(NULL),rightchild(NULL),color(0),parent(NULL)
    {}
    RBNode(Type d = Type(), RBNode<Type>* left = NULL, RBNode<Type>* right = NULL, RBNode<Type>* pr = NULL, COLOR c = RED):data(d), parent(pr),leftchild(left),rightchild(right),color(c)
    {}
private:
    COLOR color;
    Type data;
    RBNode<Type>* parent;
    RBNode<Type>* leftchild;
    RBNode<Type>* rightchild;

};
template<class Type>
class RBTree
 {
 public:
     RBTree():root(NULL)
     {}
 public:
     bool Insert(const Type & x)
     {
         return Insert(root, x);
     }
 protected:
     bool Insert(RBNode<Type>* &t, const Type &x)
     {
         RBNode<Type>* p = t;
         RBNode<Type> *pr = NULL;
         while(p != NULL)
         {
             if(x == p->data)
                 return false;
             pr = p;
             if(x < p->data)
                 p=p->leftchild;
             else 
                 p = p->rightchild;
         }
         p = _Buynode(x);
         if(pr == NULL)
         {
             p ->color = BLACK;
             t = p;
             return true;
         }
         if( x < pr->data)
             pr->leftchild = p;
         else
             pr ->rightchild = p;
         p->parent = pr;
         _Balance_Tree(t,p);
         return true;
     }
 protected:
    //这里的调整方法比较复杂,代码最下面有优化代码,仔细阅读世界独有,走马观花竹篮打水
     void _Balance_Tree(RBNode<Type>* &t, RBNode<Type>* q)
     {
         while(q->parent != NULL && q->parent->color == RED)//p->parent != NULL 是为了保证循环条件成立不会造成程序的崩溃,提高了程序的严谨性
         {
             RBNode<Type> * s =NULL;
             if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
             {
                 s = q->parent->parent->rightchild;
                 if((q == q->parent->leftchild && s==NULL) || q == q->parent->leftchild &&s!=NULL && s->color==BLACK)// /
                 {
                     q->parent ->color = BLACK;
                     q->parent->parent -> color = RED;
                     if(s != NULL)
                         s->color = RED;
                     RotateR(q->parent->parent);
                 }
                 else if((q == q->parent->rightchild && s==NULL) || q == q->parent->rightchild &&s!=NULL && s->color==BLACK)// /
                 {
                     q->parent->parent->color = RED;
                     q->color = BLACK;
                     RotateLR(q->parent->parent);
                 }
                 else if(q == q->parent->leftchild && s->color == RED)
                 {
                    q->color = BLACK;
                    RotateR(q->parent->parent);
                    if(q->parent->parent!= NULL && q->parent->parent->color == RED)
                    {
                        q = q->parent;
                        continue;
                    }

                    else
                        break;

                 }
                  else if(q == q->parent->rightchild && s->color == RED)
                 {
                     q->parent->color = BLACK;
                     RotateLR(q->parent->parent);
                     if(q->parent != NULL && q->parent->color == RED)
                     {
                         q=q->parent;
                         continue;
                     }
                     else 
                         break;
                 }
             }
             else
             {
                  s = q->parent->parent->leftchild;
                  if((q == q->parent->leftchild && s==NULL) || q == q->parent->leftchild &&s!=NULL && s->color==BLACK)// /
                 {
                     q ->color = BLACK;
                     q->parent->parent->color = RED;
                     RotateRL(q->parent->parent);

                 else if((q == q->parent->rightchild && s==NULL) || q == q->parent->rightchild &&s!=NULL && s->color==BLACK)// /
                 {
                     q->parent->parent->color = RED;
                     q->parent->color = BLACK;
                     if(s != NULL)
                         s->color = RED;
                     RotateL(q->parent->parent);
                 }
                 else if(q == q->parent->leftchild && s->color == RED)
                 {
                    q->parent->color = BLACK;
                    RotateRL(q->parent->parent);
                    if(q->parent->parent->color == BLACK)
                        break;
                    else
                    {
                        q = q->parent;
                        continue;
                    }

                 }
                  else if(q == q->parent->rightchild && s->color == RED)
                 {
                     q->parent->color = BLACK;
                     RotateL(q->parent->parent);
                     if(q->parent->color == RED)
                     {
                         q=q->parent;
                         continue;
                     }
                     else 
                         break;
                 }
             }
         }
         t->color = BLACK;
     }
 protected:
     RBNode<Type>* RotateR(RBNode<Type> *ptr)
     {
         RBNode<Type> * subR = ptr;
         ptr = subR->leftchild;
         subR->leftchild = ptr->rightchild;
         if(ptr->rightchild != NULL)
             ptr->rightchild ->parent = subR;
         ptr->rightchild = subR;
         if(subR->parent == NULL)
             root = ptr;
         else
         {
             if(subR == subR->parent->leftchild)
                 subR->parent->leftchild = ptr;
             else
                 subR->parent->rightchild = ptr;
         }
         ptr->parent = subR->parent;/////////
         subR->parent = ptr;
         return ptr;
     }
     void RotateL(RBNode<Type>* ptr)
     {
         RBNode<Type>* subL = ptr;
         ptr = subL->leftchild;
         subL->rightchild = ptr->leftchild;
         if(ptr->leftchild != NULL)
             ptr->leftchild->parent = subL;

         if(subL->parent == NULL)
             root = ptr;
         else
         {
             if(subL == subL->parent->leftchild)
                 subL->parent->leftchild = ptr;
             else
                 subL->parent->rightchild = ptr;
         }
         ptr->parent = subL->parent;
         subL->parent = ptr;
     }
     void RotateRL(RBNode<Type>* ptr)
     {
         RBNode<Type>* subR = ptr->rightchild;
         RBNode<Type>* subL = ptr;
         ptr = subR->leftchild;
         subR->leftchild = ptr->rightchild;
         if(ptr->rightchild != NULL)
             ptr->rightchild->parent = subR;
         ptr->rightchild = subR;
         subL->rightchild = ptr->leftchild;
         if(ptr->leftchild != NULL)
             ptr->leftchild->parent = subL;
         ptr->leftchild = subL;
         if(subL->parent == NULL)
             root = ptr;
         else
         {
             if(subL == subL->parent ->leftchild)
                 subL->parent ->leftchild = ptr;
             else
                 subL->parent->rightchild = ptr;
         }
         ptr->parent = subL->parent;
         subL->parent = ptr;
         subR->parent = ptr;
     }
     void RotateLR(RBNode<Type>* ptr)
     {
         RBNode<Type>* subR = ptr;
         RBNode<Type>* subL = ptr->leftchild;
         ptr = subL->rightchild;
         subL->rightchild = ptr->leftchild;
         if(ptr->leftchild != NULL)
             ptr->leftchild ->parent = subL;
         ptr->leftchild = subL;
         subR->leftchild = ptr->rightchild;
         if(ptr->rightchild != NULL)
             ptr->rightchild->parent = subR;
         ptr->rightchild = subR;
         if(subR->parent == NULL)
             root = ptr;
         else
         {
             if(subR == subR->parent->leftchild)
                 subR->parent->leftchild = ptr;
             else
                 subR->parent->rightchild = ptr;
         }
         ptr->parent = subR->parent;
         subL->parent = ptr;
         subR->parent = ptr;
     }
 private:
     RBNode<Type>* _Buynode(const Type x)
     {
         RBNode<Type>* new1 = new RBNode<Type>(x);
         return new1;
     }
 private:
     RBNode<Type>* root;
 };

三、对于平衡调整的代码优化:

对与调整的模块的优化:

/*优化说明:在节点插入的同时,我们需要考虑其伯父节点是否存在,如果存在我们看其伯父节点是否为红色,如果是只需要将伯父节点和父节点的颜色改为黑色并把祖父节点颜色调为红色,改为在树中插入祖父节点来向上调整即可,这里优化的还有我们最多只需要对节点进行两次单旋转即可达到目的*/
 void _Balance_Tree(RBNode<Type>* &t, RBNode<Type>* q)
     {
         while(q->parent->color == RED)
         {
              RBNode<Type> * s =NULL;
             if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
             {
                 s = q->parent->parent->righthchild;
                 if( s != NULL && s->color = RED)
                 {
                     q->parent->color = BLACK;
                     s -> color = BLACK;
                     q->parent->parent->color = RED;
                     q = q->parent;
                     continue;
                 }
                 else if(q = q->parent->rightchild)
                 {
                     q = q->parent;///////////为下面单转做铺垫
                     RotateL(q);
                 }
                 q->parent->color = BLACK;
                 q->parent->parent = RED;
                 RotateR(q->parent->parent);
             }
             else
             {
                  if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
             {
                 s = q->parent->parent->lefthchild;
                 if( s != NULL && s->color = RED)
                 {
                     q->parent->color = BLACK;
                     s -> color = BLACK;
                     q->parent->parent->color = RED;
                     q = q->parent->parent;
                     continue;
                 }
                 else if(q == q->parent->leftchild)
                 {
                      q = q->parent;
                     RotateR(q);
                 }
                  q->parent->color = BLACK;
                 q->parent->parent = RED;
                 RotateL(q->parent->parent);
             }
         }
     }

如果你认真阅读了博客,相信你已经对红黑树有了一定的了解,自己亲手编程将会让你能够掌握红黑树节点的增加。在普通调整和优化后的调整两种方法调整得到的最终红黑树的结果是不相同的,但是经过调整后的红黑树任然正确。还是那句话走马观花竹篮打水,仔细阅读世界独有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值