Rb树简介

红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单 路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。(性质3、性质4保证了红黑树最长的路径不超过最短路径的两倍)

如图所示:

红黑树是满足下面红黑性质的二叉搜索树

1. 每个节点,不是红色就是黑色的

2. 根节点是黑色的

3. 如果一个节点是红色的,则它的两个子节点是黑色的

4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

好,现在了解了红黑树的特性之后,我们来开始创建红黑树。

  1. //红黑树的节点的结构
  1. template<class K,class V>
  2. struct RedBlaceTreeNode
  3. {
  4. typedef RedBlaceTreeNode<K, V> Node;
  5. RedBlaceTreeNode(const K& key,const V& value)
  6. :_left(NULL), _right(NULL), _parent(NULL)
  7. , _key(key), _value(value), _col(RED)
  8. {}
  9.  
  10. Node* _left;
  11. Node* _right;
  12. Node* _parent;
  13. K _key;
  14. V _value;
  15. Sign _col;
  16. };

//红黑树的结构

  1. template<class K,class V>
  2. class RedBlaceTree
  3. {
  4. typedef RedBlaceTreeNode<K, V> Node;
  5. public:
  6. RedBlaceTree()
  7. :_root(NULL)
  8. {}
  9. public:
  10. bool _Push(const K& key, const V& value);
  11. void _LeftSpin(Node*& parent);
  12. void _RightSpin(Node*& parent);
  13. void _LeftRightSpin(Node*& parent);
  14. void _RightLeftSpin(Node*& parent);
  15.  
  16. /*Check*/
  17. //1. 每个节点,不是红色就是黑色的
  18. //2. 根节点是黑色的
  19. //3. 如果一个节点是红色的,则它的两个子节点是黑色的
  20. //4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
  21. void _Inorder(){ Inorder(_root); }
  22. void Inorder(Node* root);
  23. protected:
  24. Node* _root;
  25. };

//创建红黑树的函数 _Push()

插入的几种情况

cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

1.第一种情况 cur为红,p为红,g为黑,u存在且为红 则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。( 还挺简单  O(∩_∩)O   继续往下看↓↓)

2.第二种情况 cur为红,p为红,g为黑,u不存在/u为黑 p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转 p、g变色--p变黑,g变红

3.第三种情况 cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转 则转换成了情况2

  1. template<class K, class V>
  2. bool RedBlaceTree<K, V>::_Push(const K& key, const V& value)
  3. {
  4. Node* cur = _root;
  5. Node* parent = NULL;
  6. if (_root == NULL)
  7. {
  8. _root = new Node(key, value);
  9. _root->_col = BLACK;
  10. }
  11. else
  12. {
  13. while (cur)
  14. {
  15. parent = cur;
  16. if (key > cur->_key)
  17. {
  18. cur = cur->_right;
  19. }
  20. else if (key < cur->_key)
  21. {
  22. cur = cur->_left;
  23. }
  24. else
  25. {
  26. return false;
  27. }
  28. }
  29. cur = new Node(key, value);
  30. if (key > parent->_key)
  31. {
  32. parent->_right = cur;
  33. cur->_parent = parent;
  34. }
  35. else
  36. {
  37. parent->_left = cur;
  38. cur->_parent = parent;
  39. }
  40.  
  41. if (parent->_col == RED) //如果父亲节点为红色就需要调整
  42. {
  43. bool sign = false; //标记位,用来标记grandparent是否为根节点
  44. while (cur->_parent)
  45. {
  46. Node* grandparent = NULL;
  47. Node* uncle = NULL;
  48. parent = cur->_parent;
  49. grandparent = parent->_parent;
  50.  
  51. if (grandparent) //如果祖父节点存在
  52. {
  53. if (grandparent == _root)
  54. {
  55. sign = true; //标记祖父节点是否为根节点
  56. }
  57.  
  58. if (parent->_key > grandparent->_key) //确定叔父节点
  59. {
  60. uncle = grandparent->_left;
  61. }
  62. else
  63. {
  64. uncle = grandparent->_right;
  65. }
  66.  
  67. //第一种情况:cur为红,p为红,g为黑,u存在且为红
  68. if (uncle && uncle->_col == RED)
  69. {
  70. parent->_col = BLACK;
  71. uncle->_col = BLACK;
  72. grandparent->_col = RED;
  73. if (sign)
  74. {
  75. break;
  76. }
  77. cur = grandparent;
  78. }
  79.  
  80. //第二种情况:cur为红,p为红,g为黑,u不存在/u为黑(单旋)
  81. //第三种情况:cur为红,p为红,g为黑,u不存在/u为黑(双旋)
  82. else
  83. {
  84. //第二
  85. if (grandparent->_left == parent && parent->_left == cur)
  86. {
  87. grandparent->_col = RED;
  88. parent->_col = BLACK;
  89. _RightSpin(grandparent);
  90. if (sign)
  91. {
  92. _root = grandparent;
  93. }
  94. break;
  95. }
  96. else if (grandparent->_right == parent && parent->_right == cur)
  97. {
  98. grandparent->_col = RED;
  99. parent->_col = BLACK;
  100. _LeftSpin(grandparent);
  101. if (sign)
  102. {
  103. _root = grandparent;
  104. }
  105. break;
  106. }
  107. //第三
  108. else if (grandparent->_left == parent && parent->_right == cur)
  109. {
  110. grandparent->_col = RED;
  111. cur->_col = BLACK;
  112. _LeftRightSpin(grandparent);
  113. if (sign)
  114. {
  115. _root = grandparent;
  116. }
  117. break;
  118. }
  119. else if (grandparent->_right == parent && parent->_left == cur)
  120. {
  121. grandparent->_col = RED;
  122. cur->_col = BLACK;
  123. _RightLeftSpin(grandparent);
  124. if (sign)
  125. {
  126. _root = grandparent;
  127. }
  128. break;
  129. }
  130. }
  131. }
  132. else //cur 的上面只有一层
  133. {
  134. break;
  135. }
  136. }
  137. }
  138. }
  139. _root->_col = BLACK;
  140. }

平衡搜索树(二) Rb 红黑树的更多相关文章

  1. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  2. 谈c++ pb_ds库(二) 红黑树大法好

    厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...

  3. 红黑树(二)之 C语言的实现

    概要 红黑树在日常的使用中比较常用,例如Java的TreeMap和TreeSet,C++的STL,以及Linux内核中都有用到.之前写过一篇文章专门介绍红黑树的理论知识,本文将给出红黑数的C语言的实现 ...

  4. 大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转

    前言 11.1新的一月加油!这个购物狂欢的季节,一看,已囊中羞涩!赶紧来恶补一下红黑树和2-3树吧!红黑树真的算是大名鼎鼎了吧?即使你不了解它,但一定听过吧?下面跟随我来揭开神秘的面纱吧! 一.2-3 ...

  5. 红黑树(R-B Tree)

    R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). ...

  6. 【红黑树】的详细实现(C++)

    红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键 ...

  7. 红黑树(四)之 C++的实现

    概要 前面分别介绍红黑树的理论知识和红黑树的C语言实现.本章是红黑树的C++实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章. 目录1. 红黑树的介绍2. 红黑树的C++ ...

  8. 红黑树(五)之 Java的实现

    概要 前面分别介绍红黑树的理论知识.红黑树的C语言和C++的实现.本章介绍红黑树的Java实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章.还是那句老话,红黑树的C/C+ ...

  9. 第十四章 红黑树——C++代码实现

    红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键 ...

随机推荐

  1. Linux Shell编程(19)——测试与分支

    case和select结构在技术上说不是循环,因为它们并不对可执行的代码块进行迭代.但是和循环相似的是,它们也依靠在代码块的顶部或底部的条件判断来决定程序的分支.在代码块中控制程序分支case (in ...

  2. 利用python分析nginx日志

    最近在学习python,写了个脚本分析nginx日志,练练手.写得比较粗糙,但基本功能可以实现. 脚本功能:查找出当天访问次数前十位的IP,并获取该IP来源,并将分析结果发送邮件到指定邮箱. 实现前两 ...

  3. intellij idea 2016版破解方法

    之前办法不能用了,现在最新方法,打开http://idea.lanyus.com,直接获取验证码即可

  4. C++Primer第5版学习笔记(三)

    C++Primer第5版学习笔记(三) 第四/五章的重难点内容           你可以点击这里回顾第三章内容       因为第五章的内容比较少,因此和第四章的笔记内容合并.       第四章是 ...

  5. A*寻路算法的探寻与改良(一)

    A*寻路算法的探寻与改良(一) by:田宇轩                                                                    第一部分:这里我们主 ...

  6. sqlplus乱码

    使用SecureCRT或是pietty_ch连接到一台安装有Oracle DB 10g的RHEL4.2的机器,linux使用的shell是默认的bash. 在bash提示符下,使用Del键或者Back ...

  7. 20个 Unix/Linux 命令技巧

    让我们用这些Unix/Linux命令技巧开启新的一年,提高在终端下的生产力.我已经找了很久了,现在就与你们分享. 删除一个大文件 我在生产服务器上有一个很大的200GB的日志文件需要删除.我的rm和l ...

  8. 402. Remove K Digits

    (English version is after the code part) 这个题做起来比看起来容易,然后我也没仔细想,先速度刷完,以后再看有没有改进. 用这个来说: 1 2 4 3 2 2 1 ...

  9. SQL 查询条件放在LEFT OUTER JOIN 的ON语句后与放在WHERE中的区别

    这两种条件放置的位置不同很容易让人造成混淆,以致经常查询出莫名其妙的结果出来,特别是副本的条件与主表不匹配时,下面以A,B表为例简单说下我的理解. 首先要明白的是: 跟在ON 后面的条件是对参与左联接 ...

  10. BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]

    1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...