红黑树简单介绍
红黑树是一种满足:
- 根是黑色的
- 红色边必须为左子树,且不能有两条连续红边
- 不存在一个节点有2条红边
- 根节点到空节点的黑边相等
红黑树是一种大致平衡的二叉树,所以在插入、删除和查找操作时能保证在最坏的情况下时间复杂度为O(lgn)。
二叉搜索树在最坏情形下(当插入的元素是递增的时候),时间复杂度为O(n)。
所以红黑树在linux内核、构造关联数组等被大量使用。
查找
这个没什么好说,和二叉搜索树类似。主要说下面的插入和删除。
插入
由于插入的节点是红色节点,则可能出现插入之后不满足红黑树的性质。所以需要用红黑树的两个基本操作 左旋 和 右旋 来维持红黑树的性质。
平衡被破坏的情况:
- 在红色节点上
左边插入:右旋得到左右两个红色节点,然后翻转节点颜色
右边插入:左旋得到两条连续红边,再右旋转得到两个红色节点之后翻转节点颜色 - 在黑色节点上
右边插入:左旋将红色节点旋转到左边
删除
首先我们来考虑如何删除最小节点
由于直接删除也会破坏红黑树的性质,所以我们需要向上层借红色节点来保证被删除的节点是红色节点。当删除的是最底层的红色节点时,树的根节点到所有空节点的黑高不变,所以不会破坏平衡。
同时这里需要介绍一个重要的操作是翻转节点颜色的逆操作(reverseFlipNode),即将当前节点的颜色设置成黑色,把节点两个孩子的颜色设置成红色。这样就能把红色节点迁移到下层去并且不改变树的高度(根节点除外)。正是由于有这一性质我们才能向上层借节点到下层。
下面来讨论借节点的情况(从树根开始):
情况1:节点的颜色是红色,左子树是黑色,左子树的左子树也是黑色。
这个说明我们下面可能没有节点的颜色是红色的,也就是没有节点能借。所以我们使用reverseFlipNode操作可以将本层的红色节点向下传递到两个孩子上,这样就能保证下面一层一定有红色节点可用。
但是这里可能出现的情况是:做完reverseFlipNode操作后,节点的右子树的左子树是红色,这种情况在我们最后恢复红色节点位置的时候会出现问题(右旋操作会将这个左子树的颜色直接变成黑色),所以我们需要执行fixNode操作,将这个节点的右子树右旋,然后再将该节点左旋来保证之后能正常恢复。
情况2:节点的左子树是红色 或 节点的左子树的左子树是红色。
这说明我们下面已经有红色节点可以用了,所以我们不需要做使用reverseFlipNode操作。
具体实现步骤(递归):
递归出口:节点的左子树为空,删除节点并返回空。
如果根节点的孩子都是黑色则设置根节点颜色为红色。
执行上述两种情况来将红边传递到下层保证最左节点可以向上层借到节点。
递归左子树。
如果节点左右子树都是红色,则翻转节点颜色。
如果节点左子树是黑色,右子树是红色,则左旋。
再考虑删除最大节点
删除最大节点与删除最小节点类似,只是我们是删除最右边的节点,这里也要分几种情况:
情况1:节点是红色,左子树不是红色,右子树的左子树不是红色。
这里利用reverseFlipNode操作将红色节点传递给下一层。
情况2:节点是红色,左子树不是红色,右子树的左子树是红色。
下层有红色节点所以这里不做任何操作。
情况3:节点的左子树是红色,右子树的左子树不是红色。
这里利用左旋操作将红色节点旋转到左边保证右子树有红色节点可以借。
情况4:节点的左子树是红色,右子树的左子树也是红色。
这里不做任何操作。
具体实现步骤(递归):
递归出口:节点的右子树为空,如果节点左子树也为空则删除节点返回空,否则右旋。
如果根节点的孩子都是黑色则设置根节点颜色为红色。
执行上述几种情况保证右子树有节点可借。
如果节点左右子树都是红色,则翻转节点颜色。
如果节点左子树是黑色,右子树是红色,则左旋。
删除节点
在我们有了删除最小节点和删除最大节点的思路后,删除节点就是沿用上面两个方法的思路实现。
具体实现步骤(递归):
若 key > node->key,执行删除最大节点的情况保证下层有红色节点,递归右子树
若 key < node->key,执行删除最小节点的情况保证下层有红色节点,递归左子树
若 key = node->key,则:
当node是红色且左子树为空时,直接删除节点并返回NULL
当node是红色且左子树不为空且右子树为空时,删除节点并将node赋值成左子树且颜色和左子树相同
当node是红色且左子树不为空且右子树不为空时,执行reverseFlipNode操作并将右子树最小值min复制到node,同时删除node
当node是黑色时,这说明node的左子树是红色,所以右旋并递归右子树
如果节点左右子树都是红色,则翻转节点颜色。
如果节点左子树是黑色,右子树是红色,则左旋。
代码实现
#ifndef RBT_H
#define RBT_H
#include <iostream>
enum Color
{
RED,
BLACK
};
template<typename K, typename V>
struct Node
{
K key;
V val;
int N;
Color color;
Node<K,V>* lNode;
Node<K,V>* rNode;
Node()
{
this->lNode = NULL;
this->rNode = NULL;
}
Node(K key, V val)
{
this->key = key;
this->val = val;
this->N = 1;
this->color = RED;
this->lNode = NULL;
this->rNode = NULL;
}
};
template<typename K, typename V>
class RBT
{
public:
RBT();
~RBT();
V get(const K& key) const;
void put(const K& key, const V& val);
void del(const K& key);
bool contain(const K& key) const;
int size() const;
void clean();
void print() const;
K minKey() const;
void delMin();
void delMax();
int countLevel() const;
protected:
Node<K,V>* root;
Node<K,V>* rotateLeft(Node<K,V>* node);
Node<K,V>* rotateRight(Node<K,V>* node);
void filpNode(Node<K,V>* node);
void reverseFlipNode(Node<K,V>* node);
Node<K,V>* fixNode(Node<K,V>* node);
Node<K,V>* put(Node<K,V>* node, const K& key, const V& val);
V get(Node<K,V>* node, const K& key) const;
bool contain(Node<K,V>* node, const K& key) const;
Node<K,V>* del(Node<K,V>* node, const K& key);
void clean(Node<K,V>* node);
int size(Node<K,V>* node) const;
void print(Node<K,V>* node) const;
K minKey(Node<K,V>* node) const;
Node<K,V>* delMin(Node<K,V>* node);
Node<K,V>* delMax(Node<K,V>* node);
bool isRed(Node<K,V>* node);
int countLevel(Node<K,V>* node) const;
};
//构造 析构函数
template<typename K, typename V>
RBT<K,V>::RBT()
{
this->root = NULL;
}
template<typename K, typename V>
RBT<K,V>::~RBT()
{
clean(this->root);
}
/********************************************************************
函数名称: isRed
函数参数: @node 节点指针
函数说明: 判断节点的颜色
返回值: 成功返回true 失败返回false
*********************************************************************/
template<typename K, typename V>
bool RBT<K,V>::isRed(Node<K,V>* node)
{
if (node == NULL || node->color == BLACK)
return false;
else
return true;
}
/********************************************************************
函数名称: put
函数说明: 放入键值对<key,value> 若存在则将原有的value替换成新的value
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::put(const K& key, const V& val)
{
this->root = put(this->root, key, val);
}
template<typename K, typename V>
Node<K,V>* RBT<K,V>::put(Node<K,V>* node, const K& key, const V& val)
{
if (node == NULL)
return new Node<K,V>(key, val);
if (key > node->key)
node->rNode = put(node->rNode, key, val);
else if (key < node->key)
node->lNode = put(node->lNode, key, val);
else
node->val = val;
if (isRed(node->rNode) && !isRed(node->lNode))
node = rotateLeft(node);
if (node->lNode != NULL && isRed(node->lNode) && isRed(node->lNode->lNode))
node = rotateRight(node);
if (isRed(node->lNode) && isRed(node->rNode))
filpNode(node);
node->N = size(node->lNode) + size(node->rNode) + 1;
return node;
}
/********************************************************************
函数名称: get
函数说明: 获取指定key的value
返回值: value
*********************************************************************/
template<typename K, typename V>
V RBT<K,V>::get(const K& key) const
{
return get(this->root, key);
}
template<typename K, typename V>
V RBT<K,V>::get(Node<K,V>* node, const K& key) const
{
if (node == NULL)
return NULL;
if (key > node->key)
return get(node->rNode, key);
else if (key < node->key)
return get(node->lNode, key);
else
return node->val;
}
/********************************************************************
函数名称: clean
函数说明: 清空表
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::clean()
{
clean(this->root);
this->root = NULL;
}
template<typename K, typename V>
void RBT<K,V>::clean(Node<K,V>* node)
{
if (node == NULL)
return ;
clean(node->lNode);
clean(node->rNode);
delete node;
}
/********************************************************************
函数名称: size
函数说明: 无
返回值: 表的大小
*********************************************************************/
template<typename K, typename V>
int RBT<K,V>::size() const
{
return size(this->root);
}
template<typename K, typename V>
int RBT<K,V>::size(Node<K,V>* node) const
{
if (node == NULL)
return 0;
return size(node->rNode) + size(node->lNode) + 1;
}
/********************************************************************
函数名称: del
函数说明: 删除某个key
返回值: 无
*********************************************************************/
template<typename K ,typename V>
void RBT<K,V>::del(const K& key)
{
this->root = del(this->root, key);
}
template<typename K, typename V>
Node<K,V>* RBT<K,V>::del(Node<K,V>* node, const K& key)
{
if (node == NULL)
return NULL;
if (!isRed(this->root->lNode) && !isRed(this->root->rNode))
this->root = RED;
if (key > node->key)
{
if (isRed(node->lNode))
node = rotateRight(node);
if (node->rNode != NULL && isRed(node) && !isRed(node->rNode) && !isRed(node->rNode->lNode))
reverseFlipNode(node);
node->rNode = del(node->rNode, key);
}
else if (key < node->key)
{
if (node->lNode != NULL && isRed(node) && !isRed(node->lNode) && !isRed(node->lNode->lNode))
reverseFlipNode(node);
if (node->rNode != NULL && isRed(node->rNode) && isRed(node->rNode->lNode))
node = fixNode(node);
node->lNode = del(node->lNode, key);
}
else
{
if (isRed(node))
{
if (node->lNode == NULL)
{
delete node;
return NULL;
}
else
{
node->key = minKey(node->rNode);
node->val = get(node->key);
node->rNode = delMin(node->rNode);
}
}
else
{
node = rotateRight(node);
node->rNode = del(node->rNode, key);
}
}
if (isRed(node->rNode) && !isRed(node->lNode))
node = rotateLeft(node);
if (isRed(node->lNode) && isRed(node->rNode))
filpNode(node);
node->N = size(node->rNode) + size(node->lNode) + 1;
return node;
}
/********************************************************************
函数名称: print
函数说明: 打印表中内容
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::print() const
{
print(this->root);
}
template<typename K, typename V>
void RBT<K,V>::print(Node<K,V>* node) const
{
if (node == NULL)
return ;
print(node->lNode);
std::cout << node->key << " : " << node->val << " : " << node->N << " : " << node->color << std::endl;
print(node->rNode);
}
/********************************************************************
函数名称: contain
函数说明: 是否包含key
返回值: 包含返回true 不包含返回false
*********************************************************************/
template<typename K, typename V>
bool RBT<K,V>::contain(const K& key) const
{
return contain(this->root, key);
}
template<typename K, typename V>
bool RBT<K,V>::contain(Node<K,V>* node, const K& key) const
{
if (node == NULL)
return false;
if (key > node->key)
get(node->rNode, key);
else if (key < node->key)
get(node->lNode, key);
else
return true;
}
/********************************************************************
函数名称: rotateLeft
函数参数: 需要旋转的节点指针
函数说明: 将右节点旋转到左边并设置为红色
返回值: 旋转后的树根指针
*********************************************************************/
template<typename K, typename V>
Node<K,V>* RBT<K,V>::rotateLeft(Node<K,V>* node)
{
Node<K,V>* rNode = node->rNode;
node->rNode = rNode->lNode;
rNode->lNode = node;
rNode->color = node->color;
node->color = RED;
node->N = size(node->lNode) + size(node->rNode) + 1;
rNode->N = size(rNode->lNode) + size(rNode->rNode) + 1;
return rNode;
}
/********************************************************************
函数名称: rotateRight
函数参数: 需要旋转的节点指针
函数说明: 将左节点旋转到右边并设置为红色
返回值: 旋转后的树根指针
*********************************************************************/
template<typename K, typename V>
Node<K,V>* RBT<K,V>::rotateRight(Node<K,V>* node)
{
Node<K,V>* lNode = node->lNode;
node->lNode = lNode->rNode;
lNode->rNode = node;
lNode->color = node->color;
node->color = RED;
node->N = size(node->lNode) + size(node->rNode) + 1;
lNode->N = size(lNode->lNode) + size(lNode->rNode) + 1;
return lNode;
}
/********************************************************************
函数名称: flipNode
函数参数: 节点指针
函数说明: 将节点的左右子树的颜色变成黑色 同时节点颜色变成红色
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::filpNode(Node<K,V>* node)
{
node->color = RED;
node->lNode->color = BLACK;
node->rNode->color = BLACK;
}
/********************************************************************
函数名称: reverseFlipNode
函数参数: @node 节点指针
函数说明: 反向翻转节点和子节点的颜色 将节点颜色变成黑色 子节点红色
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::reverseFlipNode(Node<K,V>* node)
{
node->color = BLACK;
node->lNode->color = RED;
node->rNode->color = RED;
}
/********************************************************************
函数名称: fixRedNode
函数参数: @node 节点指针
函数说明: 修复反向反转后节点 node->rNode->lNode 为红色的情况
返回值:
*********************************************************************/
template<typename K, typename V>
Node<K,V>* RBT<K,V>::fixNode(Node<K,V>* node)
{
node->rNode = rotateRight(node->rNode);
node = rotateLeft(node);
return node;
}
/********************************************************************
函数名称: minKey
函数参数: 无
函数说明: 返回表中最小的key
返回值: key
*********************************************************************/
template<typename K, typename V>
K RBT<K,V>::minKey() const
{
return minKey(this->root);
}
template<typename K, typename V>
K RBT<K,V>::minKey(Node<K,V>* node) const
{
if (node->lNode == NULL)
return node->key;
else
minKey(node->lNode);
}
/********************************************************************
函数名称: delMin
函数参数: 无
函数说明: 删除表中最小key 需要保证节点的颜色是红色
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::delMin()
{
this->root = delMin(this->root);
}
template<typename K, typename V>
Node<K,V>* RBT<K,V>::delMin(Node<K,V>* node)
{
if (node == NULL)
return NULL;
if (node->lNode == NULL)
{
delete node;
return NULL;
}
if (!isRed(this->root->lNode) && !isRed(this->root->rNode))
this->root = RED;
if (isRed(node) && !isRed(node->lNode) && !isRed(node->lNode->lNode))
reverseFlipNode(node);
if (node->rNode != NULL && isRed(node->rNode) && isRed(node->rNode->lNode))
node = fixNode(node);
node->lNode = delMin(node->lNode);
//恢复红黑树的性质
if (isRed(node->lNode) && isRed(node->rNode))
filpNode(node);
if (!isRed(node->lNode) && isRed(node->rNode))
node = rotateLeft(node);
node->N = size(node->lNode) + size(node->rNode) + 1;
return node;
}
/********************************************************************
函数名称: delMax
函数参数: 无
函数说明: 删除树中最大key 需要保证节点的颜色是红色
返回值: 无
*********************************************************************/
template<typename K, typename V>
void RBT<K,V>::delMax()
{
this->root = delMax(this->root);
}
template<typename K, typename V>
Node<K,V>* RBT<K,V>::delMax(Node<K,V>* node)
{
if (node == NULL)
return NULL;
if (node->rNode == NULL)
{
if (isRed(node->lNode))
node = rotateRight(node);
else
{
delete node;
return NULL;
}
}
if (!isRed(this->root->lNode) && !isRed(this->root->rNode))
this->root = RED;
if (isRed(node->lNode) && !isRed(node->rNode->lNode))
node = rotateRight(node);
if (isRed(node) && !isRed(node->lNode) && !isRed(node->rNode->lNode))
reverseFlipNode(node);
node->rNode = delMax(node->rNode);
if (isRed(node->lNode) && isRed(node->rNode))
filpNode(node);
if (isRed(node->rNode) && !isRed(node->lNode))
node = rotateLeft(node);
node->N = size(node->lNode) + size(node->rNode) + 1;
return node;
}
template<typename K, typename V>
int RBT<K,V>::countLevel() const
{
return countLevel(this->root);
}
#endif
本文详细介绍了红黑树的性质、基本操作(插入、删除、查找)以及如何通过左旋、右旋和翻转节点颜色来维持红黑树的平衡特性。红黑树在保证高效查找的同时,通过红边和黑边的特殊规则实现了动态平衡,使其在Linux内核、构造关联数组等领域广泛应用。

2万+

被折叠的 条评论
为什么被折叠?



