目录
红黑树:基于AVL树改进
红黑树的性质
红黑树基本结构
insert基本结构
新增节点的默认颜色为红色
节点性质总结
情况一: cur为红,p为红,g为黑,u存在且为红
情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑(单旋+变色)
情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑(双旋+变色)
insert代码实现
验证是否为红黑树
源码链接
红黑树:基于AVL树改进
AVL树控制平衡因子,严格要求左右子树高度差不超过1,所以他的效率一直都是保持在O(logN)左右,但严格要求平衡导致其需要更多次的旋转
如果不严格要求平衡,只需要达到近似平衡,保持其性能还是处于logN数量级,减少旋转次数,可提升性能(AVL树的高度平衡是因为其通过大量的旋转来完成的,所以对于经常发生删除和插入的结构,红黑树的效率会更优,并且红黑树的实现比起AVL更加容易且易于控制,所以实际中使用红黑树更多)
红黑树确保最长路径不超过最短路径的二倍,在最坏情况下,增删查改效率是O(2logN)。
红黑树概念
红黑树是一种二叉搜索树,需要在每个结点增加一个存储位表示结点的颜色,分别是Red/Black。
通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保最长路径不超过最短路径的二倍,因而接近平衡
红黑树的性质
控制住颜色的规则(满足下面的性质),红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色,则它的两个孩子结点是黑色 (没有连续红节点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点(每条路径黑色节点数量相同)
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
(性质5出题:空树也是红黑树,性质5中规定树中的空指针域为叶子节点,因此空树也有节点)
根据规则3,4可以推导出:存在最短路径一定是全黑,存在最长路径一定是一黑一红
红黑树基本结构
基本结构与AVL树相似,只是把平衡因子换成枚举标识颜色,满足性质1
enum Color
{
RED,
BLACK
};
template
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Color _col;
pair _kv;
RBTreeNode(const pair& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _col(BLACK)
{}
};
template
class RBTree
{
public:
typedef RBTreeNode Node;
private:
Node* _root;
};
insert基本结构
插入分为两个步骤:
1.按照二叉搜索树的特性插入
2.满足红黑树的性质调节颜色
insert基本结构,唯一需要改变的就是当root为根时,变为黑色,满足性质2
template
class RBTree
{
public:
typedef RBTreeNode Node;
bool insert(const pair& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->left;
}
else if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
}
else if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
cur->_parent = parent;
}
private:
Node* _root;
};
新增节点的默认颜色为红色
如果此时插入30,新增的节点我们设置为红色,违反规则3
如果此时插入30,新增的节点我们设置为黑色,违反规则4
如果新增颜色为黑色,违反规则4,整棵树每个路径的颜色节点也都需要