【C++】-- 红黑树详解(二)

简介: 【C++】-- 红黑树详解

三、红黑树插入

1.插入节点

插入节点分为2步:

(1) 先查找,如果树中已存在该节点,则插入失败

(2)树中不存在该节点,插入

1. //插入
2.  pair<Node*, bool> Insert(const pair<K, V>& kv)
3.  {
4.    if (_root == nullptr)
5.    {
6.      _root = new Node(kv);
7.      _root->_col = BLACK;
8.      return make_pair(_root, true);
9.    }
10. 
11.     //1.先看树中,kv是否存在
12.     Node* parent = nullptr;
13.     Node* cur = _root;
14.     while (cur)
15.     {
16.       if (cur->_kv.first < kv.first)
17.       {
18.         //kv比当前节点值大,向右走
19.         parent = cur;
20.         cur = cur->_right;
21.       }
22.       else if (cur->_kv.first > kv.first)
23.       {
24.         //kv比当前节点值小,向左走
25.         parent = cur;
26.         cur = cur->_left;
27.       }
28.       else
29.       {
30.         //kv和当前节点值相等,已存在,插入失败
31.         return make_pair(cur, false);
32.       }
33.     }
34. 
35.     //2.走到这里,说明kv在树中不存在,需要插入kv,并且cur已经为空,parent已经是叶子节点了
36.     Node* newNode = new Node(kv);
37.     newNode->_col = RED;
38.     if (parent->_kv.first < kv.first)
39.     {
40.       //kv比parent值大,插入到parent的右边
41.       parent->_right = newNode;
42.       cur->_parent = parent;
43.     }
44.     else
45.     {
46.       //kv比parent值小,插入到parent的左边
47.       parent->_left = newNode;
48.       cur->_parent = parent;
49.     }
50.     cur = newNode;
51. 
52.     return make_pair(cur, true);
53.   }

2.控制颜色

所以在插入节点之后,为了满足红黑树的性质,还需要调整节点颜色:

(1)父亲为黑色

如果父亲是黑色,那么不需要调整,4个规则都满足,插入已完成

(2)父亲是红色

如果父亲是红色,违反了规则(3),需要调整颜色

这时就需要对树中的节点进行颜色处理了。

四、红黑树颜色处理

所有插入的新节点颜色都是红色,当父亲是红色时,需要进行颜色处理,分3种情况进行处理。在这3种情况中,cur为新插入节点,p为父亲节点,u为叔叔节点,g为祖父节点。下面的树都可能是一棵完整的树,也有可能是一棵子树。

1.cur红,p红,g黑,u存在且为红

当cur为红,p为红,g为黑,u存在且为红时,为了满足红黑树的性质,处理方法:将p和u变黑,g变红

(1)抽象图

如下a、b、c、d、e都是子树:

(1)假如g是根节点,根据红黑树性质,根节点必须是黑色,那就把g再变黑就好了

(2)假如g不是根节点,g是子树,那么g还有parent节点。

①如果g的parent是黑色,满足红黑树性质,那么停止调整。

②如果g的parent是红色,就破坏了规则(3),那么还需要继续向上调整。

调整方法为:把g当作cur,继续向上调整,直到p不存在,或p存在且为黑停止。

(2)具象图

①g是根节点,直接把p和u变黑,g变红

②g不是根节点,g是子树,把p和u变黑,g变红之后,还要继续向上调整,直到p不存在,或p存在且为黑停止

2. cur为红,p为红,g为黑,u为黑或u不存在(单旋)

这种情况下,g、p、cur形成直线,先看cur为红,p为红,g为黑,u为黑的情况

这是由情况一cur红,p红,g黑,u存在且为红处理以后变换而来,比如以下情况:

在这种情况下,cur原来的颜色一定是黑色,只不过在处理的过程当中,将cur的颜色变成了红色,所以cur不是新增节点,而是新增节点的祖先节点。

(1)抽象图

如下a、b、c、d、e都是子树,由于要旋转,所以要分为两种情况:当p是g的左子树,cur是p的左子树时,g右单旋,p变黑,g变红:

当p是g的右子树,cur是p的右子树时,g左单旋,p变黑,g变红:

(2)具象图

cur是新增节点的祖先节点,那么a、b一定不为空,由于从g到u的路径上有2个黑色节点,那么a和b都存在一个黑色节点,因此,c中也有一个黑色节点,才能满足每条路径上有相同数目的黑色节点。因此d、e要么同时不存在,要么同时为空。

当p是g的左子树,cur是p的左子树时,将节点g右单旋,p变黑,g变红:

当p是g的右子树,cur是p的右子树时,将节点g左单旋,p变黑,g变红:

再看cur为红,p为红,g为黑,u不存在的情况:

u不存在的情况更为简单,假如p是g的左子树,cur是p的左子树,将节点g右单旋,p变黑,g变红即可

假如p是g的右子树,cur是p的右子树,将节点g左单旋,p变黑,g变红即可

3.cur为红,p为红,g为黑,u不存在或u为黑(双旋)

这种情况下g、p、cur形成折线,先看cur为红,p为红,g为黑,u为黑的情况:

(1)抽象图

当p是g的左子树,cur是p的右子树时,处理方法:p左单旋,g右单旋,cur变黑,g变红

当p是g的右子树,cur是p的左子树时,处理方法:p右单旋,就变成了情况二

(2)具象图

当p是g的左子树,cur是p的右子树时,将p左单旋,g右单旋,cur变黑,g变红

当p是g的右子树,cur是p的左子树,p右单旋,g左单旋,p变黑,g变红

再看cur为红,p为红,g为黑,u不存在的情况,u不存在的情况更为简单:

当p是g的左子树,cur是p的右子树时,将p左单旋,g右单旋,cur变黑,g变红

当p是g的右子树,cur是p的左子树,p右单旋就变成了情况二:

相关文章
|
3月前
|
C++
c++的学习之路:27、红黑树
c++的学习之路:27、红黑树
40 4
|
3月前
|
测试技术 C++
C++进阶--红黑树
C++进阶--红黑树
|
3月前
|
编译器 C++ 容器
【C++学习手札】基于红黑树封装模拟实现map和set
【C++学习手札】基于红黑树封装模拟实现map和set
|
3月前
|
存储 关系型数据库 数据库
【数据结构】—红黑树(C++实现)
【数据结构】—红黑树(C++实现)
|
3月前
|
C++ 容器
【C++】红黑树模拟实现STL中的map与set
【C++】红黑树模拟实现STL中的map与set
|
8天前
|
关系型数据库 C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
15 0
|
1月前
|
Java C++ Python
【C++】手撕红黑树
【C++】手撕红黑树
14 1
|
2月前
|
关系型数据库 C++
【c++】红黑树
【c++】红黑树
12 0
|
3月前
|
Java C语言 C++
从C语言到C++_28(红黑树RedBlackTree)概念+插入接口实现(上)
从C语言到C++_28(红黑树RedBlackTree)概念+插入接口实现
32 4
|
3月前
|
C语言
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现(下)
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现
34 3