引子:
我们在学习avl搜索二叉树时,知道avl是高度差不超过1的,因此是“绝对平衡的”,那有没有一种“接近平衡”的树呢?让它在这方面轻松一点,更加高效一点?答案是有的,set与map的底层就给出了答案--红黑树,红黑树是一种自平衡的二叉搜索树,它在计算机科学中被广泛使用,特别是在需要频繁插入和删除操作的数据结构中。红黑树的名称来源于它的节点颜色,可以是红色或黑色。这种数据结构能够保证在任何情况下,从根到叶子的最长路径不会超过最短路径的两倍长。
红黑树的性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
注意:红黑树的这些特性确保了树的平衡性,查找操作的最坏情况时间复杂度能够保持在O(log n)。红黑树常用于实现关联数组,如C++ STL中的map
和set。
红黑树插入的三种情况:
前提:新节点的默认颜色是红色,cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
本人觉得情况二和情况三是在情况一的变化后形成的,因为在情况二和情况三中,cur的颜色为红,不可能为新增节点来得,大家可自行思考
情况一: cur为红,p为红,g为黑,u存在且为红
图:只给出一种情况,如有左右旋,请情况自行考虑
解决方式:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整
情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑
图:只给出一种情况,如有左右旋,请情况自行考虑
解决方式:p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反, p为g的右孩子,cur为p的右孩子,则进行左单旋转 p、g变色--p变黑,g变红
情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑
图:只给出一种情况,如有左右旋,请情况自行考虑
解决方式:p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反, p为g的右孩子,cur为p的左孩子,则针对p做右单旋转 则转换成了情况2
自实现代码:
#pragma once
#include<iostream>
#include<set>
using namespace std;
enum Color
{
RED,
BLACK
};
template<class T>
class RBTreeNode
{
public:
T _Data;
RBTreeNode* _left;
RBTreeNode* _parent;
RBTreeNode* _right;
Color _col;
RBTreeNode(const T&data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_Data(data)
{}
};
//迭代器
template<class T>
class RBTreeIterator
{
public:
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T> self;
Node* _node;
Node* _root;
RBTreeIterator(Node*node,Node*root)
:_node(node)
,_root(root)
{}
self& operator++()
{
Node* leftMost = _node->_right;
if (_node->_right)
{
leftMost = leftMost->_left;
while (leftMost)
{
leftMost = leftMost->_left;
}
_node = leftMost;
}
else
{
Node* current = _node;
Node* parent = _node->_parent;
if (parent && parent->_right == current)
{
/*parent = parent->_parent;
cur = parent;*/
current = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if (_node == nullptr)
{
//找最右节点
Node* rightMost = _root;
while (rightMost && 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;
}
T& 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 K_of_T>
class RBTree
{
public:
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T> iterator;
RBTree() = default;
//构造函数
RBTree(const T&root)
:_root(root)
{}
//拷贝构造函数,树形节点要一个一个拷贝
RBTree(const RBTree& h)
{
_root = copy(h._root);
}
//重载=
RBTree& operator=(RBTree h)
{
swap(_root, h._root);
return *this;
}
//析构函数,注意开辟了空间后,对于树形结构的节点要一个一个删除
~RBTree()
{
Destory(_root);
_root = nullptr;
}
iterator Begin()
{
Node* leftMost = _root;
while (leftMost && leftMost->_left)
{
leftMost = leftMost->_left;
}
return iterator(leftMost,_root);
}
iterator End()
{
return iterator(nullptr,_root);
}
//寻找
Node* Find(const K& key)
{
K_of_T kot;
Node* cur = _root;
while (cur)
{
if (kot(cur->_Data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_Data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
//插入
pair<iterator,bool>insert(const T& data)
{
//空树新增节点,也是红黑树
Node* root = _root;
if (root == nullptr)
{
root = new Node(data);
_root = root;
_root->_col = BLACK;
return make_pair(iterator(_root, _root), true);
}
//红黑树大逻辑
K_of_T kot;
Node* cur = _root;
Node* parent = nullptr;
//要先找到,插入位置
while (cur)
{
if (kot(data) < kot(cur->_Data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_Data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(iterator(cur, _root), false);
}
}
cur = new Node(data);
// 新增节点。颜色红色给红色
cur->_col = RED;
Node* newNode = cur;
if (kot(parent->_Data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//更改颜色
//现在cur为新增节点
while (parent && parent->_col==RED)
{
Node* grandfather = parent->_parent;
//找出叔叔节点
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//情况一
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况二
// g
// p u
//c
if (parent->_left == cur)
{
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
//情况三
// g
// p u
// c
//
//双旋
RotateL(parent);
RotateR(grandfather);
//注意cur与parent调了一下位置
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
//情况一
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况二
// g
// u p
// c
if (cur == parent->_right)
{
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//情况三
// g
// u p
// c
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
//确保根节点为黑的
_root->_col = BLACK;
return make_pair(iterator(newNode, _root), true);
}
int Height()
{
return _Height(_root);
}
int Size()
{
return _Size(_root);
}
//中序有序,避免了_root是内部private的加密
void _InOrder()
{
_InOrder(_root);
cout << endl;
}
//进行检验
bool IsBalance()
{
//空树也是红黑树
if (_root == nullptr)
return true;
//根节点是黑的
if (_root->_col == RED)
{
return false;
}
// 每条路径上的黑节点数目一样
int refNum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
++refNum;
}
cur = cur->_left;
}
return Check(_root, 0, refNum);
}
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->_col == RED && root->_parent->_col == RED)
{
cout << root->_kv.first << "存在连续的红色节点" << endl;
return false;
}
if (root->_col == BLACK)
{
blackNum++;
}
return Check(root->_left, blackNum, refNum)
&& Check(root->_right, blackNum, refNum);
}
//计算有效的节点
int _Size(Node* root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}
//计算树的高度,利用递归
int _Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//中序遍历
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
//左根右;
_InOrder(root->_left);
cout << root->_kv.first << " :" << root->_kv.second << " ";
_InOrder(root->_right);
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
subR->_left = parent;
parent->_parent = subR;
Node* parent_parent = parent->_parent;
if (parent_parent == nullptr)
{
_root = subR;
parent_parent = nullptr;
}
else
{
if (parent_parent->_left == parent)
{
parent_parent->_left = subR;
}
else if (parent_parent->_right == parent)
{
parent_parent->_right = subR;
}
subR->_parent = parent_parent;
}
}
//右旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
parent->_parent = subL;
Node* parent_parent = parent->_parent;
if (parent_parent == nullptr)
{
_root = subL;
parent_parent = nullptr;
}
else
{
if (parent_parent->_left == parent)
{
parent_parent->_left = subL;
}
else if (parent_parent->_right == parent)
{
parent_parent->_right = subL;
}
subL->_parent = parent_parent;
}
}
//销毁
void Destory(Node* root)
{
if (root == nullptr)
{
return;
}
Destory(root->_left);
Destory(root->_right);
Destory(root->_parent);
delete root;
}
//拷贝
Node* copy(const Node*& root)
{
if (root == nullptr)
{
return nullptr;
}
Node* temp = new Node(root->_kv);
temp->_left = copy(root->_left);
temp->_right = copy(root->_right);
temp->_parent = copy(root->_parent);
return temp;
}
Node* _root = nullptr;
};
结语:本文已经实现了一部分map与set的接口,下集我们相约map与set封装,哈希等好知识点,感谢大家的支持!
以下是一些接口:
namespace my_map
{
template<class K, class V>
class map
{
public:
struct K_of_T
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
typedef typename RBTree<K, K, K_of_T>::iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
pair<iterator, bool>Insert(const pair<K, V>& kv)
{
_t.Insert(kv);
}
private:
RBTree<K, pair<K, V>, K_of_T> _t;
};
}
namespace my_set
{
template<class K>
class set
{
public:
struct K_of_T
{
const K& operator()(const K& key)
{
return key;
}
};
typedef typename RBTree<K, K, K_of_T>::iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
pair<iterator, bool>insert(const K& key)
{
return _t.insert(key);
}
private:
RBTree<K, K, K_of_T> _t;
};
}