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

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

4.红黑树节点插入代码

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.     //如果父亲存在,且父亲颜色为红就要处理
53.     while (parent && parent->_col == RED)
54.     {
55.       //关键看叔叔
56.       Node* grandfather = parent->_parent;
57.       if (parent == grandfather->_left)//父亲是祖父的左子树
58.       {
59.         Node* uncle = grandfather->_right;
60.         //情况一:叔叔存在且为红
61.         if (uncle->_col == RED)
62.         {
63.           parent->_col = uncle->_col = BLACK;
64.           grandfather->_col = RED;
65. 
66.           //继续向上调整
67.           cur = grandfather;
68.           parent = cur->_parent;
69.         }
70.         else//情况二+情况三:叔叔不存在或叔叔存在且为黑
71.         {
72.           //情况二:单旋
73.           if (cur == parent->_left)
74.           {
75.             RotateR(grandfather);
76.             parent->_col = BLACK;
77.             grandfather->_col = RED;
78.           }
79.           else//情况三:双旋
80.           {
81.             RotateL(parent);
82.             RotateR(grandfather);
83.             cur->_col = BLACK;
84.             grandfather->_col = RED;
85.           }
86.           break;//插入结束
87.         }
88.       }
89.       else//父亲是祖父的右子树
90.       {
91.         Node* uncle = grandfather->_left;
92.         //情况一:叔叔存在且为红
93.         if (uncle && uncle->_col == RED)
94.         {
95.           parent->_col = uncle->_col = BLACK;
96.           grandfather->_col = RED;
97. 
98.           //继续往上调整
99.           cur = grandfather;
100.          parent = grandfather->_parent;
101.        }
102.        else//情况二+情况三:叔叔不存在或叔叔存在且为黑
103.        {
104.          //情况二:单旋
105.          if (cur == parent->_right)
106.          {
107.            RotateL(grandfather);
108.            parent->_col = BLACK;
109.            grandfather->_col = RED;
110.          }
111.          else//情况三:双旋
112.          {
113.            RotateR(parent);
114.            RotateL(grandfather);
115.            cur->_col = BLACK;
116.            grandfather->_col = RED;
117.          }
118.          break;//插入结束
119.        }
120.      }
121. 
122.    }
123.    _root->_col = BLACK;
124. 
125.    return make_pair(newNode, true);
126.  }

五、红黑树查找

查找比较简单,递归向左走或向右走:

1.  //查找
2.  Node* Find(const K& key)
3.  {
4.    Node* cur = _root;
5.    while (cur)
6.    {
7.      if (cur->_kv.first < key)//key比当前节点小,就向右查找
8.      {
9.        cur = cur->_right;
10.       }
11.       else if (cur->_kv.first > key)//key比当前节点大,就向左查找
12.       {
13.         cur = cur->_left;
14.       }
15.       else//找到了
16.       {
17.         return cur;
18.       }
19.     }
20.     return nullptr;//空树,直接返回
21.   }

六、红黑树检查是否平衡

检查是否平衡还是要用到递归子函数

(1)需要判断是否满足红黑树的4条性质

(2)计算最左路径上的黑色节点个数,递归路径时,需要计算该条路径上的黑色节点个数是否和最左路径上的节点个数相等

1.  bool _CheckBalance(Node* root, int blackNum, int count)
2.  {
3.    if (root == nullptr)
4.    {
5.      if (count != blackNum)
6.      {
7.        cout << "黑色节点数量不相等" << endl;
8.        return false;
9.      }
10.       return true;
11.     }
12. 
13.     if (root->_col == RED && root->_parent->_col == RED)
14.     {
15.       cout << "存在连续红色节点" << endl;
16.       return false;
17.     }
18. 
19.     if (root->_col == BLACK)
20.     {
21.       count++;
22.     }
23. 
24.     return _CheckBalance(root->_left, blackNum, count)
25.       && _CheckBalance(root->_right, blackNum, count);
26.   }
27. 
28.   //检查是否平衡
29.   bool CheckBlance()
30.   {
31.     if (_root == nullptr)
32.     {
33.       return true;
34.     }
35. 
36.     if (_root->_col == RED)
37.     {
38.       cout << "根节点为红色" << endl;
39.       return false;
40.     }
41. 
42.     //找最左路径做黑色节点数量参考值
43.     int blackNum = 0;
44.     Node* left = _root;
45.     while (left)
46.     {
47.       if (left->_col == BLACK)
48.       {
49.         blackNum++;
50.       }
51.       left = left->_left;
52.     }
53. 
54.     int count = 0;
55.     return _CheckBlance(_root, blackNum, count);
56.   }

对于以下红黑树,递归过程如下:

七、红黑树遍历

遍历也很简单,中序递归遍历左子树和右子树:

1.  //遍历
2.  void _InOrder(Node* root)
3.  {
4.    if (root == nullptr)
5.    {
6.      return;
7.    }
8. 
9.    _InOrder(root->_left);
10.     cout << root->_kv.first << ":" << root->_kv.second << endl;
11.     _InOrder(root->_right);
12.   }
13. 
14.   void InOrder()
15.   {
16.     _InOrder(_root);
17.     cout << endl;
18.   }

八、红黑树验证

1. #include "RedBlackTree.h"
2. 
3. void TestRBTree()
4. {
5.  //,1,3,5,15,7,16,14
6.  int a[] = { 4,2,6,1,3,5,15,7,16 };
7.  RBTree<int, int> t;
8.  for (auto e : a)
9.  {
10.     t.Insert(make_pair(e, e));
11.   }
12. 
13.   t.InOrder();
14.   //cout << t.CheckBalance() << endl;
15. }
16. 
17. int main()
18. {
19.   TestRBTree();
20.   return 0;
21. }

插入成功:

相关文章
|
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