目录
红黑树是一种自平衡的二叉搜索树,广泛用于计算机科学中以实现高效的数据存储和检索。它在许多标准库中得到应用,例如 C++ 的 std::map
和 std::set
都基于红黑树实现。本文将介绍红黑树的基本概念、性质、操作以及如何在 C++ 中实现红黑树。
1. 红黑树的基本概念
红黑树是一种具有以下性质的二叉搜索树:
- 节点颜色:每个节点都是红色或黑色。
- 根节点:根节点是黑色。
- 叶子节点:所有的叶子节点(NULL 指针)都是黑色。
- 红色节点:红色节点的子节点都是黑色(即红色节点不能有两个连续的红色节点)。
- 路径一致性:从任何节点到其所有子孙叶子节点的路径包含相同数量的黑色节点。
这些性质确保了树的平衡性,从而保证了基本操作的对数时间复杂度。
2. 红黑树的性质
这些性质帮助红黑树维持平衡,确保在最坏情况下操作的时间复杂度为 O(logn)O(\log n)O(logn):
- 根节点为黑色。
- 每个叶子节点(NIL节点)为黑色。
- 红色节点的两个子节点都是黑色。
- 从任何节点到其每个叶子节点的路径上,必须包含相同数量的黑色节点。
3. 红黑树的操作
3.1 插入操作
插入操作分为两个步骤:
- 标准二叉搜索树插入:将新节点插入到红黑树中,按照二叉搜索树的规则。
- 修复红黑树:通过调整树的结构和节点颜色,恢复红黑树的性质。这包括重新着色和旋转操作。
3.2 删除操作
删除操作涉及:
- 标准二叉搜索树删除:删除节点,并保持二叉搜索树的结构。
- 修复红黑树:通过复杂的重新着色和旋转操作,恢复红黑树的性质。
4. C++ 中的红黑树实现
在 C++ 标准库中,红黑树的实现被封装在 std::map
和 std::set
中。这里我们提供一个简单的红黑树实现示例:
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
//枚举 :黑 白
enum Color
{
RED,
BLACK
};
//创建树节点,存储三叉链:父亲,左节点,右节点
template <class T>
struct RBTreeNode
{
T _data; //数据 泛型化
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _color; //存储颜色
RBTreeNode(const T& data)
:_data(data)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
{}
};
//迭代器
template <class T ,class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;//传入的节点指针
Node* _root;
//初始化
RBTreeIterator(Node* node, Node* root)
:_node(node)
,_root(root)
{}
Self& operator++()
{
if (_node->_right)
{
//右不为空,右子树的最左节点
Node* leftMost = _node->_right;
while (leftMost->_left)
{
leftMost = leftMost->_left;
}
_node = leftMost;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
Self& operator--()
{
if (_node == nullptr)
{
Node* rightMost = _root;
while (rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else if (_node->_left)
{
//左不为空,左子树的最右节点
Node* rightMost = _node->_left;
while (rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!= (const Self& s)
{
return _node != s._node;
}
bool operator== (const Self& s)
{
return _node == s._node;
}
};
template <class K,class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T&, T*> Iterator;
typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
RBTree() = default;
RBTree(const RBTree& t)
{
_root = Copy(t._root);
}
Iterator Begin()
{
Node* lastleft = _root;
while (lastleft && lastleft->_left)
{
lastleft = lastleft->_left;
}
return Iterator(lastleft,_root);
}
Iterator End()
{
return Iterator(nullptr,_root);
}
ConstIterator Begin() const
{
Node* leftMost = _root;
while (leftMost && leftMost->_left)
{
leftMost = leftMost->_left;
}
return ConstIterator(leftMost, _root);
}
ConstIterator End() const
{
return ConstIterator(nullptr, _root);
}
RBTree& operator=(RBTree t)
{
swap(_root, t._root);
return *this;
}
~RBTree()
{
Destroy(_root);
_root = nullptr;
}
pair<Iterator, bool> Insert(const T& data)
{
//如果红黑树为空,直接插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_color = BLACK;
return make_pair(Iterator(_root, _root), true);
}
KeyOfT kot;
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(Iterator(cur, _root), false);
}
}
cur = new Node(data);
Node* newnode = cur;
//新增红色节点
cur->_color = RED;
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while (parent && parent->_color == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
// g
// p u
// c
if (uncle&& uncle->_color == RED)
{
//u存在且为红,
// 把父亲和叔叔变黑,爷爷变红,继续向上处理
parent->_color = uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//u存在且为黑,或不存在 旋转+变色
// g
// p u
// c
if (parent->_left == cur)
{
RotateRight(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
}
else
{
// g
// p u
// c
RotateLeft(parent);
RotateRight(grandfather);
cur->_color = BLACK;
grandfather->_color = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_right;
if (uncle&& uncle->_color == RED)
{
//u存在且为红,
// 把父亲和叔叔变黑,爷爷变红,继续向上处理
parent->_color = uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//u存在且为黑,或不存在 旋转+变色
// g
// u p
// c
if (parent->_right == cur)
{
RotateLeft(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
}
else
{
// g
// u p
// c
RotateRight(parent);
RotateLeft(grandfather);
cur->_color = BLACK;
grandfather->_color = RED;
}
break;
}
}
}
_root->_color = BLACK;
return make_pair(Iterator(newnode, _root), true);
}
bool IsBalance()
{
if (_root == nullptr)
return true;
if (_root->_color == RED)
{
return false;
}
// 参考值
int refNum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_color == BLACK)
{
++refNum;
}
cur = cur->_left;
}
return Check(_root, 0, refNum);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
bool Check(Node* root, int blackNum, const int refNum)
{
if (root == nullptr)
{
//cout << blackNum << endl;
if (refNum != blackNum)
{
cout << "存在黑色节点的数量不相等的路径" << endl;
return false;
}
return true;
}
if (root->_color == RED && root->_parent->_color == RED)
{
cout << root->_kv.first << "存在连续的红色节点" << endl;
return false;
}
if (root->_color == BLACK)
{
blackNum++;
}
return Check(root->_left, blackNum, refNum)
&& Check(root->_right, blackNum, refNum);
}
void RotateLeft(Node* parent)
{
//_rotateNum++;
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* parentParent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (parentParent == nullptr)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parent == parentParent->_left)
{
parentParent->_left = subR;
}
else
{
parentParent->_right = subR;
}
subR->_parent = parentParent;
}
}
void RotateRight(Node* parent)
{
//_rotateNum++;
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* parentParent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (parentParent == nullptr)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (parent == parentParent->_left)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
void Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
Node* Copy(Node* root)
{
if (root == nullptr)
{
return;
}
Node* newRoot = new Node(root->_key, root->_value);
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
return newRoot;
}
private:
Node* _root = nullptr;
};
总结
红黑树是一种自平衡的二叉搜索树,具有对数时间复杂度的插入、删除和查找操作。它通过特定的节点颜色和旋转操作来保持平衡。C++ 标准库中的 std::map
和 std::set
就是基于红黑树实现的。上述示例展示了红黑树的基本实现,包括节点插入和树的平衡维护。了解红黑树的基本操作和实现细节对优化数据结构和提高程序效率非常重要。