【C++】红黑树

打印 上一主题 下一主题

主题 547|帖子 547|积分 1641

前言:

   AVL树是二叉平衡搜索树,红黑树是基于AVL树的改造,是基于旋转的次数的减少。
  红黑树简介

红黑树的性质


  • 每个结点不是红色就是黑色
  • 根节点是黑色的
  • 假如一个节点是红色的,则它的两个孩子结点是黑色的
  • 对于每个结点,从该结点到其全部后代叶结点的简朴路径上,均 包罗相同数目的黑色结点
  • 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
红黑树操作

红黑树是一种自平衡的二叉搜索树,它通过在每个节点上添加颜色属性(红色或黑色)并遵循特定的规则来保持树的平衡,从而包管了插入、删除和查找操作的对数时间复杂度。
在C++中实现红黑树通常涉及以下步调:

  • 定义节点结构,包罗数据、颜色、左右子节点指针等。
  • 实现红黑树的基本操作,如插入、删除、左旋、右旋、颜色翻转等。
  • 维护红黑树的性质,确保在每次插入或删除后通过一系列旋转和颜色调解操作来规复平衡。
红黑树的实现

存储结构



  • 整体的存贮结构类似于AVL树,AVL实现平衡的需要平衡因子_bf
  • 红黑树的节点定义不是红色节点就是黑色节点,根据颜色的区分并且包管红红黑树的性质。
  1. enum Colour
  2. {
  3.     RED,
  4.     BLACK
  5. };
  6. template<class K, class V>
  7.     class RBTreeNode
  8.     {
  9.         public:
  10.         RBTreeNode<K, V>* _left;
  11.         RBTreeNode<K, V>* _right;
  12.         RBTreeNode<K, V>* _parent;
  13.         pair<K, V> _kv;
  14.         Colour _col;
  15.         RBTreeNode(const pair<K, V>& kv)
  16.             :_left(nullptr), _right(nullptr), _parent(nullptr), _col(RED), _kv(kv)
  17.             {}
  18.     };
复制代码
红黑树的插入、



  • 整体的思想和BST和AVL树是一样的左边小右边大
  1. bool insert(const pair<K, V>& kv)
  2. {
  3.     if (_root == nullptr)
  4.     {
  5.         _root = new Node(kv);
  6.         _root->_col = BLACK;
  7.         return true;
  8.     }
  9.     Node* parent = nullptr;
  10.     Node* cur = _root;
  11.     while (cur)
  12.     {
  13.         if (kv.first > cur->_kv.first)
  14.         {
  15.             parent = cur;
  16.             cur = cur->_right;
  17.         }
  18.         else if (kv.first < cur->_kv.first)
  19.         {
  20.             parent = cur;
  21.             cur = cur->_left;
  22.         }
  23.         else
  24.         {
  25.             return false;
  26.         }
  27.     }
  28.     cur = new Node(kv);
  29.     cur->_col = RED;
  30.     if (kv.first < parent->_kv.first)
  31.     {
  32.         parent->_left = cur;
  33.     }
  34.     else
  35.     {
  36.         parent->_right = cur;
  37.     }
  38.     cur->_parent = parent;、
  39.     //调账
  40.   ...
  41. }
复制代码
调解(旋转)



  • 红黑树的底层类似于AVL,仅仅是旋转次数变少,但是时间复杂度依旧是O(lgN)
左旋

  1. void RotateL(Node* parent)
  2. {
  3.         Node* cur = parent->_right;
  4.         Node* curleft = cur->_left;
  5.         parent->_right = curleft;
  6.         if (curleft)
  7.         {
  8.                 curleft->_parent = parent;
  9.         }
  10.         cur->_left = parent;
  11.         Node* ppnode = parent->_parent;
  12.         parent->_parent = cur;
  13.         if (parent == _root)
  14.         {
  15.                 _root = cur;
  16.                 cur->_parent = nullptr;
  17.         }
  18.         else
  19.         {
  20.                 if (ppnode->_left == parent)
  21.                 {
  22.                         ppnode->_left = cur;
  23.                 }
  24.                 else
  25.                 {
  26.                         ppnode->_right = cur;
  27.                 }
  28.                 cur->_parent = ppnode;
  29.         }
  30. }
复制代码
右旋

  1. void RotateR(Node* parent)
  2. {
  3.         Node* cur = parent->_left;
  4.         Node* curright = cur->_right;
  5.         parent->_left = curright;
  6.         if (curright)
  7.         {
  8.                 curright->_parent = parent;
  9.         }
  10.         cur->_right = parent;
  11.         Node* ppnode = parent->_parent;
  12.         parent->_parent = cur;
  13.         if (ppnode == nullptr)
  14.         {
  15.                 _root = cur;
  16.                 cur->_parent = nullptr;
  17.         }
  18.         else
  19.         {
  20.                 if (ppnode->_left == parent)
  21.                 {
  22.                         ppnode->_left = cur;
  23.                 }
  24.                 else
  25.                 {
  26.                         ppnode->_right = cur;
  27.                 }
  28.                 cur->_parent = ppnode;
  29.         }
  30. }
复制代码
导致红黑树的不平衡缘故原由



  • 红黑树不可以连续个连续的节点是红色
  • 包管每一个路径黑色节点数目是一样的(根据这个条件,我们要插入红色节点)
环境一



  • u节点存在,并且是红色

环境二



  • u节点不存在或者u节点为黑色

如何包管红黑树平衡



  • 我们需要寻找parent的节点的兄弟节点定义为uncle,举行判断,空,黑,红。
  • 假如是红色节点,将parent和uncle节点的颜色转换为黑色,继续向上调解
  • 假如节点不存在或者为黑的环境下,举行旋转,调解节点颜色。
  1. while (parent && parent->_col == RED)
  2. {
  3.     Node* grandparent = parent->_parent;
  4.     if (parent == grandparent->_left)
  5.     {
  6.         Node* uncle = grandparent->_right;
  7.         if (uncle && uncle->_col == RED)
  8.         {
  9.             parent->_col = uncle->_col = BLACK;
  10.             grandparent->_col = RED;
  11.             cur = grandparent;
  12.             parent = cur->_parent;
  13.         }
  14.         else//uncle is not or black
  15.         {
  16.             if (cur == parent->_left)
  17.             {
  18.                 RotateR(grandparent);
  19.                 grandparent->_col = RED;
  20.                 parent->_col = BLACK;
  21.             }
  22.             else
  23.             {
  24.                 RotateL(parent);
  25.                 RotateR(grandparent);
  26.                 grandparent->_col = RED;
  27.                 cur->_col = BLACK;
  28.             }
  29.             break;
  30.         }
  31.     }
  32.     else//parent == grandparent->_right
  33.     {
  34.         Node* uncle = grandparent->_left;
  35.         if (uncle && uncle->_col == RED)
  36.         {
  37.             grandparent->_col = RED;
  38.             parent->_col = uncle->_col= BLACK;
  39.             cur = grandparent;
  40.             parent = cur->_parent;
  41.         }
  42.         else
  43.         {
  44.             if (cur == parent->_right)
  45.             {
  46.                 RotateL(grandparent);
  47.                 parent->_col = BLACK;
  48.                 grandparent->_col = RED;
  49.             }
  50.             else
  51.             {
  52.                 RotateR(parent);
  53.                 RotateL(grandparent);
  54.                 cur->_col = BLACK;
  55.                 grandparent->_col = RED;
  56.             }
  57.         }
  58.         break;
  59.     }
  60. }
复制代码
红黑树平衡的验证



  • 根节点不需要举行验证直接返回就好
  • 根节点假如是红色的节点可以举行返回。包管根节点是黑色的
  • 红黑树的特点就是每一个路径的黑色节点数目是一样的。这时候就需要查抄黑色节点的数目
  1. bool is_balance(Node* root)
  2. {
  3.     if (root == nullptr)
  4.     {
  5.         return true;
  6.     }
  7.     if (root->_col == RED)
  8.     {
  9.         return false;
  10.     }
  11.     int stdnum = 0;
  12.     Node* cur = root;
  13.     while (cur)
  14.     {
  15.         if (cur->_col == BLACK)
  16.         {
  17.             ++stdnum;
  18.         }
  19.         cur = cur->_left;
  20.     }
  21.     return Checknum(root, 0, stdnum);
  22. }
复制代码
查抄黑色节点



  • 使用传值调用,递归实现
  • 走到根节点举行判断,假如是和标准相等的环境下,返回true。
  1. bool Checknum(Node* root, int blacknum, int stdnum)
  2. {
  3.     if (root == nullptr)
  4.     {
  5.         if (blacknum != stdnum)
  6.         {
  7.             return false;
  8.         }
  9.         return true;
  10.     }
  11.     if (root->_col == BLACK)
  12.     {
  13.         ++blacknum;
  14.     }
  15.     return Checknum(root->_left, blacknum, stdnum)
  16.         && Checknum(root->_right, blacknum, stdnum);
  17. }
复制代码
源码

  1. #pragma once
  2. #include<iostream>
  3. #include<assert.h>
  4. #include<utility>
  5. using namespace std;
  6. namespace RBTree
  7. {
  8.         enum Colour
  9.         {
  10.                 RED,
  11.                 BLACK
  12.         };
  13.         template<class K, class V>
  14.         class RBTreeNode
  15.         {
  16.         public:
  17.                 RBTreeNode<K, V>* _left;
  18.                 RBTreeNode<K, V>* _right;
  19.                 RBTreeNode<K, V>* _parent;
  20.                 pair<K, V> _kv;
  21.                 Colour _col;
  22.                 RBTreeNode(const pair<K, V>& kv)
  23.                         :_left(nullptr), _right(nullptr), _parent(nullptr), _col(RED), _kv(kv)
  24.                 {}
  25.         };
  26.         template<class K, class V>
  27.         class RBTree
  28.         {
  29.                 typedef RBTreeNode<K, V> Node;
  30.         public:
  31.                 bool is_balance()
  32.                 {
  33.                         return is_balance(_root);
  34.                 }
  35.                 bool Checknum(Node* root, int blacknum, int stdnum)
  36.                 {
  37.                         if (root == nullptr)
  38.                         {
  39.                                 if (blacknum != stdnum)
  40.                                 {
  41.                                         return false;
  42.                                 }
  43.                                 return true;
  44.                         }
  45.                         if (root->_col == BLACK)
  46.                         {
  47.                                 ++blacknum;
  48.                         }
  49.                         return Checknum(root->_left, blacknum, stdnum)
  50.                                 && Checknum(root->_right, blacknum, stdnum);
  51.                 }
  52.                 bool is_balance(Node* root)
  53.                 {
  54.                         if (root == nullptr)
  55.                         {
  56.                                 return true;
  57.                         }
  58.                         if (root->_col == RED)
  59.                         {
  60.                                 return false;
  61.                         }
  62.                         int stdnum = 0;
  63.                         Node* cur = root;
  64.                         while (cur)
  65.                         {
  66.                                 if (cur->_col == BLACK)
  67.                                 {
  68.                                         ++stdnum;
  69.                                 }
  70.                                 cur = cur->_left;
  71.                         }
  72.                         return Checknum(root, 0, stdnum);
  73.                 }
  74.                 bool insert(const pair<K, V>& kv)
  75.                 {
  76.                         if (_root == nullptr)
  77.                         {
  78.                                 _root = new Node(kv);
  79.                                 _root->_col = BLACK;
  80.                                 return true;
  81.                         }
  82.                         Node* parent = nullptr;
  83.                         Node* cur = _root;
  84.                         while (cur)
  85.                         {
  86.                                 if (kv.first > cur->_kv.first)
  87.                                 {
  88.                                         parent = cur;
  89.                                         cur = cur->_right;
  90.                                 }
  91.                                 else if (kv.first < cur->_kv.first)
  92.                                 {
  93.                                         parent = cur;
  94.                                         cur = cur->_left;
  95.                                 }
  96.                                 else
  97.                                 {
  98.                                         return false;
  99.                                 }
  100.                         }
  101.                         cur = new Node(kv);
  102.                         cur->_col = RED;
  103.                         if (kv.first < parent->_kv.first)
  104.                         {
  105.                                 parent->_left = cur;
  106.                         }
  107.                         else
  108.                         {
  109.                                 parent->_right = cur;
  110.                         }
  111.                         cur->_parent = parent;
  112.                         while (parent && parent->_col == RED)
  113.                         {
  114.                                 Node* grandparent = parent->_parent;
  115.                                 if (parent == grandparent->_left)
  116.                                 {
  117.                                         Node* uncle = grandparent->_right;
  118.                                         if (uncle && uncle->_col == RED)
  119.                                         {
  120.                                                 parent->_col = uncle->_col = BLACK;
  121.                                                 grandparent->_col = RED;
  122.                                                 cur = grandparent;
  123.                                                 parent = cur->_parent;
  124.                                         }
  125.                                         else//uncle is not or black
  126.                                         {
  127.                                                 if (cur == parent->_left)
  128.                                                 {
  129.                                                         RotateR(grandparent);
  130.                                                         grandparent->_col = RED;
  131.                                                         parent->_col = BLACK;
  132.                                                 }
  133.                                                 else
  134.                                                 {
  135.                                                         RotateL(parent);
  136.                                                         RotateR(grandparent);
  137.                                                         grandparent->_col = RED;
  138.                                                         cur->_col = BLACK;
  139.                                                 }
  140.                                                 break;
  141.                                         }
  142.                                 }
  143.                                 else//parent == grandparent->_right
  144.                                 {
  145.                                         Node* uncle = grandparent->_left;
  146.                                         if (uncle && uncle->_col == RED)
  147.                                         {
  148.                                                 grandparent->_col = RED;
  149.                                                 parent->_col = uncle->_col= BLACK;
  150.                                                 cur = grandparent;
  151.                                                 parent = cur->_parent;
  152.                                         }
  153.                                         else
  154.                                         {
  155.                                                 if (cur == parent->_right)
  156.                                                 {
  157.                                                         RotateL(grandparent);
  158.                                                         parent->_col = BLACK;
  159.                                                         grandparent->_col = RED;
  160.                                                 }
  161.                                                 else
  162.                                                 {
  163.                                                         RotateR(parent);
  164.                                                         RotateL(grandparent);
  165.                                                         cur->_col = BLACK;
  166.                                                         grandparent->_col = RED;
  167.                                                 }
  168.                                         }
  169.                                         break;
  170.                                 }
  171.                         }
  172.                         _root->_col = BLACK;
  173.                         return true;
  174.                 }
  175.                 void RotateR(Node* parent)
  176.                 {
  177.                         Node* cur = parent->_left;
  178.                         Node* curright = cur->_right;
  179.                         parent->_left = curright;
  180.                         if (curright)
  181.                         {
  182.                                 curright->_parent = parent;
  183.                         }
  184.                         cur->_right = parent;
  185.                         Node* ppnode = parent->_parent;
  186.                         parent->_parent = cur;
  187.                         if (ppnode == nullptr)
  188.                         {
  189.                                 _root = cur;
  190.                                 cur->_parent = nullptr;
  191.                         }
  192.                         else
  193.                         {
  194.                                 if (ppnode->_left == parent)
  195.                                 {
  196.                                         ppnode->_left = cur;
  197.                                 }
  198.                                 else
  199.                                 {
  200.                                         ppnode->_right = cur;
  201.                                 }
  202.                                 cur->_parent = ppnode;
  203.                         }
  204.                 }
  205.                 void RotateL(Node* parent)
  206.                 {
  207.                         Node* cur = parent->_right;
  208.                         Node* curleft = cur->_left;
  209.                         parent->_right = curleft;
  210.                         if (curleft)
  211.                         {
  212.                                 curleft->_parent = parent;
  213.                         }
  214.                         cur->_left = parent;
  215.                         Node* ppnode = parent->_parent;
  216.                         parent->_parent = cur;
  217.                         if (parent == _root)
  218.                         {
  219.                                 _root = cur;
  220.                                 cur->_parent = nullptr;
  221.                         }
  222.                         else
  223.                         {
  224.                                 if (ppnode->_left == parent)
  225.                                 {
  226.                                         ppnode->_left = cur;
  227.                                 }
  228.                                 else
  229.                                 {
  230.                                         ppnode->_right = cur;
  231.                                 }
  232.                                 cur->_parent = ppnode;
  233.                         }
  234.                 }
  235.         private:
  236.                 Node* _root = nullptr;
  237.         };
  238. }
  239.         }
  240.                 void RotateL(Node* parent)
  241.                 {
  242.                         Node* cur = parent->_right;
  243.                         Node* curleft = cur->_left;
  244.                         parent->_right = curleft;
  245.                         if (curleft)
  246.                         {
  247.                                 curleft->_parent = parent;
  248.                         }
  249.                         cur->_left = parent;
  250.                         Node* ppnode = parent->_parent;
  251.                         parent->_parent = cur;
  252.                         if (parent == _root)
  253.                         {
  254.                                 _root = cur;
  255.                                 cur->_parent = nullptr;
  256.                         }
  257.                         else
  258.                         {
  259.                                 if (ppnode->_left == parent)
  260.                                 {
  261.                                         ppnode->_left = cur;
  262.                                 }
  263.                                 else
  264.                                 {
  265.                                         ppnode->_right = cur;
  266.                                 }
  267.                                 cur->_parent = ppnode;
  268.                         }
  269.                 }
  270.         private:
  271.                 Node* _root = nullptr;
  272.         };
  273. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表