红黑树原理

我们都听过平衡二叉树(AVLTree),了解到AVL树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。AVL树的效率就是高在这个地方。如果在AVL树中插入或删除节点后,使得高度之差大于1。此时,AVL树的平衡状态就被破坏,它就不再是一棵二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理, 那么创建一颗平衡二叉树的成本其实不小. 这个时候就有人开始思考,并且提出了红黑树的理论,那么红黑树到底比AVL树好在哪里?
红黑树与AVL树的比较:
1.AVL树的时间复杂度虽然优于红黑树,但是对于现在的计算机,cpu太快,可以忽略性能差异 
2.红黑树的插入删除比AVL树更便于控制操作 
3.红黑树整体性能略优于AVL树(红黑树旋转情况少于AVL树)
红黑树的性质:红黑树是一棵二叉搜索树,它在每个节点增加了一个存储位记录节点的颜色,可以是RED,也可以是BLACK;通过任意一条从根到叶子简单路径上颜色的约束,红黑树保证最长路径不超过最短路径的二倍,因而近似平衡。
具体性质如下:
1.每个节点颜色不是黑色,就是红色
2.根节点是黑色的
3.如果一个节点是红色,那么它的两个子节点就是黑色的(没有连续的红节点)
4.对于每个节点,从该节点到其后代叶节点的简单路径上,均包含相同数目的黑色节点
你的最短路径就是全黑节点,最长路径就是一个红节点一个黑节点,最后黑色节点相同时,最长路径刚好是最短路径的两倍
红黑树的插入:
红黑树插入节点过程大致分析:
RBTree为二叉搜索树,我们按照二叉搜索树的方法对其进行节点插入
RBTree有颜色约束性质,因此我们在插入新节点之后要进行颜色调整
具体步骤如下:
1.根节点为NULL,直接插入新节点并将其颜色置为黑色
2.根节点不为NULL,找到要插入新节点的位置
3.插入新节点
4.判断新插入节点对全树颜色的影响,更新调整颜色
首先红黑树的插入其实不是那么容易实现的,以前搜索树的插入我们很容易理解现在我们首先思考一个问题,你插入节点的默认颜色是RED或BLACK? 这里我们需要根据性质来思考,首先如果插入黑节点,这个可以直接插入无论它的父亲是什么颜色,但是红黑树的性质是每条路径的黑色节点数目相同这个时候你再想想那其他路径的黑色节点数目一定比你现在少一个节点,所以调整起来是非常繁琐的. 插入红节点不需要调整其他路径,如果它的父亲为黑,那么直接插入,如果他的父亲为红那么在该路径上面开始分情况调整. 所以插入节点默认颜色一定要为红.如果为黑调节成本太大了. 
接下来开始插入节点如果插入节点的父亲为黑那么直接插入后返回不需要做任何调整. 但是如果插入节点的父亲为红,那么就需要调整了.具体的调整过程可以分为三个情况:
1.第一种情况 
cur为红,parent为红,pParent为黑,uncle存在且为红 
则将parent,uncle改为黑,pParent改为红,然后把pParent当成cur,继续向上调整。
此时对该子树进行操作,parent节点和uncle节点变为黑,pParent节点变为红,这样我们就保证该子树中每条路径中黑色节点相同并且没有连续的红节点,然后再让cur等于pParent节点继续往上继续调整。
2.第二种情况 
cur为红,parent为红,pParent为黑,uncle不存在/u为黑 
parent为pParent的左孩子,cur为parent的左孩子,则进行右单旋转;
3.第三种情况 
cur为红,p为红,g为黑,u不存在/u为黑 
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转 
则转换成了情况2 

[Java]  纯文本查看  复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
boolean Insert( const K& key, const V& value)
     {
         //根节点为空
         if (_root == NULL)
         {
             _root = new Node(key,value);
             _root->_color = BLACK;
 
             return true ;
         }
         //根节点不为空
 
         //找到新节点插入位置
         Node* parent = NULL;
         Node* cur = _root;
 
         while (cur)
         {
             if (cur->_key < key)
             {
                 parent = cur;
                 cur = cur->_right;
             }
             else if (cur->_key >key)
             {
                 parent = cur;
                 cur = cur->_left;
             }
             else
                 return false ;
         }
         //插入新节点
         cur = new Node(key, value);
         cur->_color = RED;
         if (parent->_key > key)
         {
             parent->_left = cur;
             cur->_parent = parent;
         }
         else //parent->_key < key
         {
             parent->_right = cur;
             cur->_parent = parent;
         }
 
         //插入节点后颜色的调整
         while (parent && parent->_color == RED)
         {
             Node* grandfather = parent->_parent; //grandfather颜色一定为黑色
             if (parent == grandfather->_left)
             {
                 Node* uncle = grandfather->_right;
 
                 //uncle存在且为红
                 if (uncle && uncle->_color == RED)
                 {
                     parent->_color = uncle->_color = BLACK;
                     grandfather->_color = RED;
 
                     cur = grandfather;
                     parent = cur->_parent;
                 }
                 else //uncle不存在/uncle存在且为黑
                 {
                     if (cur == parent->_right)
                     {
                         RotateL(parent);
                         swap(parent, cur);
                     }
                     RotateR(grandfather);
                     parent->_color = BLACK;
                     grandfather->_color = RED;
                 }
             }
             else //grandfather->_right==parent
             {
                 Node* uncle = grandfather->_left;
 
                 //uncle存在且为红
                 if (uncle && uncle->_color == RED)
                 {
                     parent->_color = uncle->_color = BLACK;
                     grandfather->_color = RED;
 
                     cur = grandfather;
                     parent = cur->_parent;
                 }
                 else //不存在/存在且为黑
                 {
                     if (cur == parent->_left)
                     {
                         RotateR(parent);
                         swap(cur, parent);
                     }
 
                     RotateL(grandfather);
                     parent->_color = BLACK;
                     grandfather->_color = RED;
                 }
             }
         } //end while (parent && parent->_color == RED)
 
         _root->_color = BLACK;
 
         return true ;
     }

更多免费技术资料可关注:annalin1203

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值