红黑树>
在之前实现了AVL树,其实红黑树和AVL树都是高效且平衡的二叉搜索树,增删查改的时间复杂度都是O(lg N).但是在实际应用中红黑树的应用最多,比如C++STL库--map/set,java库,Linux内核以及其他的一些库里都用到了红黑树,这是因为红黑树是不追求完全平衡的是一种近似平衡的二叉树,保证最长路径不超过最短路径的二倍,相对于AVL树来说降低了旋转的要求,所以性能会优于AVL树(这篇文章主要介绍红黑树的插入).
在上面提到了红黑树的特性是保证最长路径不超过最短路径的二倍,那仫为什仫满足这样的要求就是红黑树了呢?让我先来介绍一下红黑树的性质>
1).每个结点不是红色就是黑色.
2).根结点是黑色的.
3).如果一个结点是红色的,则它的两个子节点是黑色的(不存在连续的红结点).
4).对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点(每条路径上黑色结点的数量相等)
5).每个叶子结点都是黑色的(这里的叶子结点指的是空结点).
假设有这样的一棵树它的所有节点都是黑色的,而且满足红黑树的特性,此时再次插入新的结点要重新满足红黑树的特性4,我们只能插入红色结点,而且插入新的红色结点为了满足特性3,只能在黑色结点之间插入新的红色结点,此时最长路径上的结点数量恰好满足不超过最短路径的两倍.
红黑树的插入>
为了满足红黑树的特性4,所以新插入的结点的颜色必须为红色.
当前结点cur为红色,parent为红色,则必然存在祖父结点.因为不能存在连续的红色结点,所以祖父结点的颜色一定是黑色的.根据uncle是否存在以及uncle结点的颜色来进行不同的处理.
(1).uncle存在且uncle为红.
(2).uncle不存在或者uncle为黑色.
通过上图观察可得情况3和情况2类似,可以将情况3先进行左单旋变成和情况2类似的情况再进行右单旋,最后达到处理的效果.
在进行双旋的时候,因为双旋是分成单旋来完成的所以双旋完成第一次单旋后要修改parent和cur指针否则就会导致丢失结点的现象.
(3).当parent->_right == cur时和上述情况类似,在这里我就不多加叙述了.
代码实现区>
#pragma once
enum Colour
{
RED,
BLACK
};
template<class K,class V>
struct RBTreeNode
{
K _key;
V _value;
RBTreeNode<K,V>* _left;
RBTreeNode<K,V>* _right;
RBTreeNode<K,V>* _parent;
Colour _color;
RBTreeNode(const K& key,const V& value)
:_key(key)
,_value(value)
,_left(NULL)
,_right(NULL)
,_parent(NULL)
,_color(RED)
{}
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K,V> Node;
public:
RBTree()
:_root(NULL)
{}
bool Insert(const K& key,const V& value)
{
if(_root == NULL)
{
_root=new Node(key,value);
_root->_color=BLACK;
return true;
}
Node *parent=NULL;
Node *cur=_root;
while (cur)
{
if (cur->_key < key)
{
parent=cur;
cur=cur->_right;
}
else if (cur->_key > key)
{
parent=cur;
cur=cur->_left;
}
else
return false;
}
cur=new Node(key,value);
cur->_parent=parent;
if(parent->_key < key)
parent->_right=cur;
else
parent->_left=cur;
while (cur != _root && parent->_color == RED) //保证有父亲和祖父
{
Node *grandfather=parent->_parent;
if (grandfather->_left == parent)
{
Node *uncle=grandfather->_right;
if (uncle && uncle->_color == RED) //情况1
{
parent->_color=uncle->_color=BLACK;
grandfather->_color=RED;
//继续向上调整
cur=grandfather;
parent=cur->_parent;
}
else //uncle不存在或者uncle为黑色
{
if (parent->_right == cur) //情况3
{
_RotateL(parent);
//第一次旋转完成后更新parent和cur
swap(parent,cur);
}
_RotateR(grandfather); //情况2
grandfather->_color=RED;
parent->_color=BLACK;
break;
}
}
else //grandfather->_right == parent
{
Node *uncle=grandfather->_left;
if(uncle && uncle->_color == RED)
{
parent->_color=uncle->_color=BLACK;
grandfather->_color=RED;
cur=grandfather;
parent=cur->_parent;
}
else //uncle不存在或者uncle为黑色
{
if (parent->_left == cur)
{
_RotateR(parent);
swap(parent,cur);
}
_RotateL(grandfather);
grandfather->_color=RED;
parent->_color=BLACK;
break;
}
}
}
_root->_color=BLACK;
return true;
}
bool Find(const K& key)
{
if(_root == NULL)
return false;
Node *cur=_root;
while (cur)
{
if(cur->_key < key)
cur=cur->_right;
else if(cur->_key > key)
cur=cur->_left;
else
return true;
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout<<endl;
}
bool IsRBTree()
{
if(_root == NULL)
return true;
if(_root->_color == RED) //判断根结点是否是黑色
return false;
int count=0;
Node *cur=_root;
while (cur)
{
if(cur->_color == BLACK)
count++;
cur=cur->_left;
}
int k=0;
return _IsRBTree(_root,count,k);
}
~RBTree()
{
_Destroy(_root);
}
protected:
bool _IsRBTree(Node *root,const int count,int k)
{
if(root == NULL)
return true;
if (root->_color == RED && root->_parent->_color == RED)
{
cout<<"存在连续的红结点:"<<root->_key<<endl;
return false;
}
if(root->_color == BLACK)
++k;
if (root->_left == NULL && root->_right == NULL)
{
if(count != k)
{
cout<<"黑色结点的数量不等"<<root->_key<<endl;
return false;
}
}
return _IsRBTree(root->_left,count,k) && _IsRBTree(root->_right,count,k);
}
void _RotateL(Node *parent)
{
Node *subR=parent->_right;
Node *subRL=subR->_left;
parent->_right=subRL;
if(subRL)
subRL->_parent=parent;
subR->_left=parent;
Node *ppNode=parent->_parent;
parent->_parent=subR;
if (ppNode == NULL)
{
_root=subR;
subR->_parent=NULL;
}
else
{
if(ppNode->_left == parent)
ppNode->_left=subR;
else
ppNode->_right=subR;
subR->_parent=ppNode;
}
}
void _RotateR(Node *parent)
{
Node *subL=parent->_left;
Node *subLR=subL->_right;
parent->_left=subLR;
if(subLR)
subLR->_parent=parent;
subL->_right=parent;
Node *ppNode=parent->_parent;
parent->_parent=subL;
if (ppNode == NULL)
{
_root=subL;
subL->_parent=NULL;
}
else
{
if(ppNode->_left == parent)
ppNode->_left=subL;
else
ppNode->_right=subL;
subL->_parent=ppNode;
}
}
void _InOrder(Node *root)
{
if(root == NULL)
return ;
_InOrder(root->_left);
cout<<root->_key<<" ";
_InOrder(root->_right);
}
void _Destroy(Node *&root)
{
if(root == NULL)
return ;
Node *cur=root;
if (cur)
{
_Destroy(cur->_left);
_Destroy(cur->_right);
delete cur;
cur=NULL;
}
}
protected:
Node *_root;
};