红黑树简介
红黑树是在AVL树的基础上做出一些改变。都是在插入和删除时,对二叉树进行旋转来保证二叉树的平衡。从而保证高效的查找效率。
红黑树是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树。后来才被修改为如今的“红黑树”。
红黑树不必严格遵守高度差为1, 红黑树可以容许最高高度不超过最低高度的二倍。
这样即使我们需要搜索一个最坏的情况。也只需要搜索"二倍的以二为底n的对数"次 , n为二叉树的节点个数。
红黑树的特点
- 红黑树节点分为两个颜色(红色和黑色)的每个节点不是红色的就是黑色的;
- 根节点必为黑色的;
- 不能存在有两个连续的红色节点,所以一个红节点的左右孩子如果存在,肯定为黑色。
- 对于任意一个节点,他的左右子树包含的路径 均有数量相同的黑色节点。
因为每条路径上都有相同数量的黑节点。而又不能存在两个连续的红色节点。如果一条路径上有k个黑色节点,所以一条路径上最长的情况就是一黑一红相间,所以高度为2k; 最短的情况为只有黑色节点,则高度为k。
因为红黑树相比AVL树拥有更好的对高度差的包容性。所以在插入时可以减少大量的旋转操作。从而在实际操作中,红黑树更受到大家的喜欢。
红黑树的插入
红黑树的插入和AVL树基本相似。在找到合适的位置插入后,判断插入后的树是否满足红黑树的要求。如果不满足,则进行旋转。
enum Color
{
RED,
BLACK
};
template<class K,class V>
class RBTreeNode
{
public:
std::pair<K, V> _kv=std::make_pair(0, 0);
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
Color _col;
RBTreeNode(const std::pair<K, V>& kv)
:_kv(kv),
_left(nullptr),
_right(nullptr),
_parent(nullptr),
_col(RED)
{
}
};
那我们 在这里用了一个枚举量来标记节点的颜色。
在插入节点时,我们始终插入一个红色的节点。因为当我们插入一个红色节点时,如果插入的新节点的父节点为黑色时,我们就不需要对树进行旋转。这样可以减少操作量。
插入时的操作与普通的搜索二叉树的方法没有什么区别。
// 查找位置
if (_root == nullptr) {
_root = new Node(kv);
_root->_col = BLACK;
return std::make_pair(_root, true);
}
Node* parent = nullptr;
Node* cur = _root;
while (cur != nullptr) {
if