红黑树对比AVL树的区别就是,红黑树的旋转次数更少,但是查找的效率会略比AVL树低,因为红黑树会比AVL树高一些。
概念:
1.红黑树的根节点必须为黑色。
2.红黑树节点不允许有连续的红色。
3.叶子节点都是黑色的(此处叶子节点是指空节点)。
4.每条路径上的黑色节点相等
满足上面的4个性质,就能保证,最长路径的节点个数,不超过最短路径的二倍。
节点的定义
enum Color//定义颜色
{
red,
black
};
template <class T>
struct TreeNode
{
typedef TreeNode<T> Node;
TreeNode(const T& data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_Color(red)
,_data(data)
{}
TreeNode<T>* _left;
TreeNode<T>* _right;
TreeNode<T>* _parent;
T _data;
Color _Color;
};
插入
插入的节点一定是红色节点,因为如果插入黑色节点就不能保证,每条路径上的黑色节点相等。
插入方法就是比当前节点小就去左边,比当前节点大就去右边,知道当前节点为空,就插入。
插入之后,就要开始改变颜色或者旋转,使插入之后仍然满足红黑树的规则。
可以分为2种情况
1.舅舅存在且为红色
这是最简单的情况
为了保证不能出现连续的红节点,需要把parent和uncle变为黑色。
保证每条路径上的黑色节点相等,将grand变为红色,如果grand是root节点,那就不变,为什呢,因为这颗树可能是一颗子树,将uncle,parent变黑,如果不将grand变红,这颗子树的路径就会多出一个黑节点。
然后一直向上调整,直到是根节点或者没有连续的红节点。
2.舅舅不存在或者舅舅存在且为黑
舅舅存在且为黑的情况,说明cur是由情况1变红的。
舅舅不存在,cur一定是新插入的节点
需要进行旋转,如果cur和parent在一条线上进行,以parent右单旋。
不在一条直线对parent进行左旋,然后对grand进行右旋。
上面都是parent在左变的的情况,还有parent在右边的情况。
std::pair<iterator,bool> insert(const T& data)
{
Node* cur = _root;
Node* parent = nullptr;
if (_root == nullptr)//当root为空时
{
_root = new Node(data);
_root->_Color = black;
return std::make_pair(iterator(_root),true);
}
TofK tk;
while (cur)//寻找插入位置
{
if (tk(cur->_data) > tk(data))
{
parent = cur;
cur = cur->_left;
}
else if (tk(cur->_data) < tk(data))
{
parent = cur;
cur = cur->_right;
}
else
{
return std::make_pair(iterator(cur), false);
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_parent = parent;
if (tk(cur->_data) > tk(parent->_data))//连接父亲节点
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//开始调整颜色
while (parent != nullptr && parent->_Color == red)
{
Node* grand = parent->_parent;
if (cur->_Color == red && parent->_Color == red)//连续红节点
{
if (parent == grand->_left)//父亲是爷爷的左节点
{
Node* uncle = grand->_right;
if (uncle != nullptr && uncle->_Color == red)//舅舅存在且为红
{
parent->_Color = black;
uncle->_Color = black;
grand->_Color = red;
cur = grand;
parent = cur->_parent;
}
else if (uncle == nullptr || uncle->_Color == black)//舅舅不存在||舅舅存在且为黑
{
if (cur == parent->_left)//在一条直线上
{
RotateR(grand);
grand->_Color = red;
parent->_Color = black;
}
else//不在一条直线上
{
RotateL(parent);
RotateR(grand);
cur->_Color = black;
grand->_Color = red;
}
break;
}
}
else//父亲是爷爷的右节点
{
Node* uncle = grand->_left;
if (uncle != nullptr && uncle->_Color == red)//舅舅存在且为红
{
parent->_Color = black;
uncle->_Color = black;
grand->_Color = red;
cur = grand;
parent = cur->_parent;
}
else if (uncle == nullptr || uncle->_Color == black)//舅舅不存在||舅舅存在且为黑
{
if (cur == parent->_right)//在一条直线上
{
RotateL(grand);
grand->_Color = red;
parent->_Color = black;
}
else//不在一条直线上
{
RotateR(parent);
RotateL(grand);
cur->_Color = black;
grand->_Color = red;
}
break;
}
}
}//连续红节点
}
_root->_Color = black;
return std::make_pair(iterator(newnode), true);
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
parent->_right = subRL;
if (subRL != nullptr)
{
subRL->_parent = parent;
}
if (parent == _root)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parent == ppNode->_left)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
parent->_left = subLR;
if (subLR != nullptr)
{
subLR->_parent = parent;
}
if (parent == _root)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (parent == ppNode->_left)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}