前言
map/set/multiset/multimap的底层是二叉搜索树,而二叉搜索树也会出现一个单链表的情况,所以通过增加平衡因子来降低树的高度,这也是AVL树的实现原理,在AVL树那里有个疑惑就是不一定有平衡因子也能调节,在学习了红黑树的实现后,这个疑问的答案大概就是这个了,所以对此进行记录,以防遗忘。
关于红黑树的代码和笔记
红黑树的是给每个结点增加了颜色Red和Black,通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路径会比其他路径长出俩倍,达到这样的接近平衡的状态。
特点有:1、root结点是黑的.
2、某个结点是红的话,如果它有子节点,那么子节点是黑的
3、对于某个结点而言,其以及子节点的路径里含有黑色节点的个数是相同的。
4.空节点默认是黑的。
enum Color
{
black,
red
}
template<class K,class V>
struct RedBlackTreeNode
{
RedBlackTreeNode<K,V>* _left;
RedBlackTreeNode<K,V>* _right;
RedBlackTreeNode<K,V>* _parent;
pair<K,V> _kv;
Color _color;
RedBlackTreeNode(const pair<K,V>& kv)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_kv(kv),
_color(red)//默认红色后面好调整
{};
};
检测插入节点后,红黑树性质是否被破坏
插入默认是红色节点,如果父辈结点是黑色的,就不需要做出改变,但如果是红的,就需要进行讨论了,这里讨论不只是包含插入的情况。
1、当前的为红,父节点为红,叔叔节点为红,祖父节点为黑
这里的解决方案就是将parent、uncle节点变黑,grandpa节点变红,如果这只是某个子树的部分,cur就要指代目前的grandpa,再根据情况向上进行调整 。
后面的情况基本上属于这个的变种,代码表示这种情况:
while(parent&&parent->_color==red)
{
Node* grandparent =parent->_parent;//这里的Node 是typedef的,也就是RedBlackTreeNode<K,V>
if(grandparent->_left==parent)
{
Node* uncle=grandparent->_right;
//uncle 存在且为红
if(uncle&&uncle->_color==red)
{
parent->_color=black;
uncle->_color=black;
grandparent->_color=red;
//向上调整
cur=grandparent;
parent=cur->_parent;
}
}
}
2、当前的为红,父节点为红,祖父节点为黑,叔叔节点不存在
如果叔叔节点不存在,那么当前的红色节点必然是新插入的节点,不然父节点和当前节点必然有一个是黑的,不然不符合红色节点的字节点是黑,以及每条简单路径下黑色节点个数相同。
变换之后成为了
如果这只是某个子树的部分,cur就要指代目前的parent,再根据情况向上进行调整 。
3、当前的为红,父节点为红,祖父节点为黑,叔叔节点存在
这种情况当前的节点肯定不是插入的节点,而是先前是黑色调整之后变换成红色的,而且这里的叔叔节点也肯定是黑色,这样才符合要求,所以这里就要再次调整。
这里的情况进行右旋,再变色,如果在右边就左旋再变色,视情况而定:
A:
这里是直接右旋并变色。
B:
这里就变成了A的情况了 ,也就是先左旋再右旋。
还有其他的 情况,但本质上和上面的情况都大差不差,按照上面的逻辑进行变换就行了。
针对举例的情况进行代码表示:
while(parent&&parent->_color==red)
{
Node* grandparent =parent->_parent;//这里的Node 是typedef的,也就是
//RedBlackTreeNode<K,V>
if(grandparent->_left==parent)
{
Node* uncle=grandparent->_right;
//uncle 存在且为红
if(uncle&&uncle->_color==red)
{
parent->_color=black;
uncle->_color=black;
grandparent->_color=red;
//向上调整
cur=grandparent;
parent=cur->_parent;
}
else//uncle不存在|uncle存在且为黑
{
// g
// p u
//cur
if(cur==parent->_left)
{
rightRotation(grandparent);//这个方法的实现是在AVL树那篇里提到的
//这里了解思路即可
parent->_left=black;
grandparent->_color=red;
}
else
{
// g
// p u
// cur
leftRotation(parent);
rightRotation(grandparent);
cur->_color =black;
parent->_color=red;
grandparent->_color=red;
}
break;
}
}
else //grandparent->_right==parent
{
Node* uncle=grandparent->_left;
//uncle 存在且为红
if(uncle&&uncle->_color==red)
{
parent->_color=black;
uncle->_color=black;
grandparent->_color=red;
//向上调整
cur=grandparent;
parent=cur->_parent;
}
else
{
// g
// u p
// cur
if(cur==parent->_right)
{
leftRotation(grandparent);
grandparent->_color=red;
parent->_color=black;
}
else
{
// g
// u p
// cur
rightRotation(parent);
leftRotation(grandparent);
cur->_color=black;
grandparent->_color=red;
}
break;
}
}
}