红黑树
红黑树的概念
①红黑树与AVL树一样都是平衡二叉搜索树
②通过从任一节点到其叶子节点的所有路径上都包含相同数目的黑节点的限制,确保没有一条路径会比其他路径长出俩倍,因而是接近平衡
红黑树的性质
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的(没有连续的红结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
红黑树的极端情况
针对第三点我们很容易想到两种极端情况
虽然是AVL时间复杂度的两倍但是在log函数面前2倍并不会很大,二者相差并不大
但AVL树为了保持严格的平衡,条件更加苛刻,代价大
综合来看红黑树更优一些
用红黑树来封装map,set
定义红黑树结点
enum Colour
{
RED,
BLACK,
};
//red-black node
template <class T>
struct RBTreeNode
{
//三叉链
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;//结点储存的数据 map存储pair set存储Key
Colour _col;//结点的颜色
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)//插入新结点颜色为红色
{
}
};
红黑树的迭代器
//反向迭代器
//迭代器的适配器
template<class Iterator>
struct ReverseIterator
{
typedef typename Iterator::reference Ref;
typedef typename Iterator::pointer Ptr;
typedef ReverseIterator<Iterator> Self;
Iterator _it;//储存的是正向迭代器
ReverseIterator(Iterator it)
:_it(it)
{
}
Ref operator*()
{
return *_it;
}
Ptr operator->()
{
return _it.operator->();
}
Self& operator++()
{
--_it;
return *this;
}
Self& operator--()
{
++_it;
return *this;
}
bool operator!=(const Self& s)const
{
return _it != s._it;
}
bool operator==(const Self& s)const
{
return _it == s._it;
}
};
//正向迭代器
//结点储存的数据T
template<class T, class Ref, class Ptr>
struct _TreeIterator
{
typedef Ref reference;
typedef Ptr pointer;
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T, Ref, Ptr> Self;
Node* _node;//指向红黑树结点的指针
_TreeIterator(Node* node)
:_node(node)
{
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
//重点重载operator++ 根据中序遍历走
Self& operator++()
{
//右节点存在 访问右树最左的结点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右节点不存在的情况,向上找
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
//说明访问过了
cur = cur->_parent;
parent = parent->_parent;
}
//此时cur结点是parent的左
_node = parent;
}
//如果是最后一个结点++,则返回nullpitr
return *this;
}
//operator--()
Self& operator--()
{
//左节点存在 访问左树最右结点
if (_node->_left)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
//end--返回空节点
return *this;
}
};