标签:return 左旋转 期望 type users swa 最长路 user 删除算法










#pragma once
enum {BLACK,RED};
template<typename K,typename V>
struct RBTreeNode
{
int _color;
K _key;
V _value;
RBTreeNode<K, V> *_left;
RBTreeNode<K, V> *_right;
RBTreeNode<K, V> *_parent;
RBTreeNode(K key, V value)
:_color(RED) //默认结点是红色
, _key(key)
, _value(value)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
{}
};
template<typename K,typename V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
:_root(NULL)
{}
RBTree(const RBTree<K, V>& tree)
{
_Copy(tree._root, _root);
}
RBTree<K, V>& operator=(const RBTree<K, V>& tree)
{
if (this != &tree)
{
RBTree<K, V> tmp(tree);
swap(_root, tmp._root);
}
return *this;
}
~RBTree()
{
_Destory(_root);
}
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
cur = cur->_left;
else if (cur->_key < key)
cur = cur->_right;
else
return true;
}
return false;
}
bool Insert(const K& key, const V& value)
{
if (_root == NULL) //如果插入的结点是根节点
{
_root = new Node(key, value);
_root->_color = BLACK;
return true;
}
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
return false; //要插入的结点已经存在
}
cur = new Node(key, value);
if (parent->_key>key)
parent->_left = cur;
else
parent->_right = cur;
cur->_parent = parent;
while (cur != _root&&parent->_color == RED) //父节点是红色的需要调整
{
Node* grand = parent->_parent; //找到祖父结点
if (parent == grand->_left)
{
Node* uncle = grand->_right; //找到叔叔结点
if (uncle&&uncle->_color == RED) //叔叔结点是红色
{
grand->_color = RED;
parent->_color = BLACK;
uncle->_color = BLACK;
cur = grand;
parent = cur->_parent; //红色结点上移,需要继续判断
}
else //叔叔结点不存在或为黑色结点
{
//先处理双旋的情况
if (cur == parent->_right) //如果cur是父亲的右孩子
{
RotateL(parent); //先对parent进行左旋
parent = cur;
}
//如果cur是parent的右孩子,则经过旋转之后现在就变成了以grand右旋的情况
RotateR(grand); //对祖父结点进行右旋
parent->_color = BLACK;
grand->_color = RED;
break; //这时候就已经平衡了
}
}
else
{
Node* uncle = grand->_left;
if (uncle&&uncle->_color == RED) //如果叔叔存在且为红色
{
parent->_color = BLACK;
uncle->_color = BLACK;
grand->_color = RED; //红色结点上移,继续向上判断
cur = grand;
parent = cur->_parent;
}
else
{
//如果cur是parent的左孩子,则需要先进行右旋将双旋转换成左旋的情况
if (cur == parent->_left)
{
RotateR(parent);
parent = cur;
}
//在对祖父进行左旋
RotateL(grand);
parent->_color = BLACK;
grand->_color = RED;
break;
}
}
}
_root->_color = BLACK; //把根节点置成黑色
return true;
}
bool Remove(const K& key)
{
Node* cur = _root;
Node* parent = NULL;
Node* del = NULL;
while (cur) //寻找要删除的结点
{
if (cur->_key > key)
cur = cur->_left;
else if (cur->_key < key)
cur = cur->_right;
else
break;
}
if (cur == NULL)
return false; //没找到结点,删除失败
//如果要删除的结点有两个孩子,则先转化成只有一个孩子或者没有孩子的情况
if (cur->_left != NULL&&cur->_right != NULL)
{
Node* minRight = cur->_right; //记录要删除的结点在的右子树的最左结点
while (minRight->_left)
{
minRight = minRight->_left;
}
//采用交换删除
cur->_key = minRight->_key;
cur->_value = minRight->_value;
cur = minRight; //cur指向要删除的结点
}
parent = cur->_parent; //找到要删除的结点的父亲
del = cur; //del指向要删除的结点
if (cur->_left == NULL) //要删除的结点的左孩子为空或者不存在
{
if (cur == _root) //如果要删除的结点是根节点,则删除之后就已经平衡
{
_root = cur->_right;
if (cur->_right) //如果根节点的右孩子不为空的话,则它一定是红色
{
_root->_parent = NULL;
_root->_color = BLACK;
}
delete del;
return true;
}
//将要删除的结点的孩子链接到要删除的结点的父亲下面
if (parent->_left == cur) //cur是parent的左孩子,要删除的结点不是根节点,则一定有父亲
parent->_left = cur->_right;
else //cur是parent的右孩子,要删除的结点不是父亲,则一定有父亲
parent->_right = cur->_right;
if (cur->_right) //如果要删除的不是叶子结点的话
cur->_right->_parent = parent;
cur = del->_right; //让cur指向要删除结点的孩子
}
else
{
if (cur == _root) //要删除的结点是根节点,则根节点的左子树一定存在
{
_root = cur->_left;
_root->_parent = NULL;
_root->_color = BLACK; //根节点的左孩子不为空的话它一定是红色
delete del;
return true;
}
if (parent->_left == cur) //要删除的不是根节点,则parent一定存在
parent->_left = cur->_left;
else
parent->_right = cur->_left;
cur->_left->_parent = parent; //cur的左孩子一定存在
cur = del->_left; //让cur指向要删除结点的孩子
}
if (del->_color == RED) //如果要删除的结点就是红色的,则删除后已经平衡
{
delete del;
return true;
}
if (del->_color == BLACK&&cur&&cur->_color == RED) //如果要删除的结点是黑色的,且它的孩子是红色的,将孩子改为黑色就平衡了
{
cur->_color = BLACK;
delete del;
return true;
}
//要删除的结点是黑色的,且它的孩子为NULL或者是黑色的
while (parent)
{
if (parent->_left == cur) //如果要删除的结点是父亲结点的左孩子
{
Node* subR = parent->_right; //subR是parent的右孩子,且一定存在
if (subR->_color == RED) //parent的右孩子是红色的
{
RotateL(parent); //对parent进行左旋,旋转之后染色,因为cur路径上仍然少一个结点,所以继续检索cur
parent->_color = RED;
subR->_color = BLACK;
}
else //如果subR是黑色的
{
Node* subRL = subR->_left;
Node* subRR = subR->_right;
if (parent->_color == BLACK &&
((subRL == NULL&&subRR == NULL) ||
(subRL&&subRR&&subRL->_color == BLACK&&subRR->_color == BLACK))) //如果parent以及subR和subR的孩子都为空
{
subR->_color = RED; //使得subR这条路径上减少一个黑色结点,再判断向上parent
cur = parent;
parent = cur->_parent;
}
else
{
if (parent->_color == RED) //如果父节点是红色
{
if ((subRL == NULL&&subRR == NULL) ||
(subRL&&subRR&&subRL->_color == BLACK&&subRR->_color == BLACK))
{
parent->_color = BLACK; //将父节点变为黑色
subR->_color = RED; //右孩子变为红,相当于在cur这条路径上曾加了一个黑色
break; //满足平衡,直接退出
}
}
if (subRL->_color = RED) //如果subRL为红色,先对subR进行右旋转换为左单选的情况
{
RotateR(subR);
subR = subRL; //让subR指向旋转之后新的父节点
}
//到这就是左单旋的情况
RotateL(parent); //对parent进行做单选
if (parent->_color == RED) //将旋转之后新的父节点subR变为与原来父节点一样的颜色
subR->_color = RED;
else
subR->_color = BLACK;
parent->_color = BLACK; //将原来父节点染成黑色的
subR->_right->_color = BLACK; //因为subR的右子树上少了一颗黑色结点,所以要将红色染黑
break; //树已经平衡
}
}
}
else
{
Node* subL = parent->_left; //要删除的结点在parent的右子树,且一定存在
if (subL->_color == RED) //parent的左孩子是红色的,则通过旋转让parent左右两边黑色结点个数相对
{
RotateR(parent); //让paret右旋
//让左右两边黑色结点相同,都少一个结点,再继续判断cur,
parent->_color = RED;
subL->_color = BLACK;
}
else //如果parent的左孩子是 黑色的
{
Node* subLR = subL->_right;
Node* subLL = subL->_left;
//如果父节点与subL的孩子都是黑色的,subLL的孩子要么全为空,要么全为黑
if (parent->_color == BLACK &&
((subLL == NULL&&subLR == NULL) ||
(subLL&&subLR&&subLL->_color == BLACK&&subLR->_color == BLACK)))
{
subL->_color = RED; //使得subL这条路径上少一个黑色接点,再继续向上判断
cur = parent;
parent = cur->_parent;
}
else
{
if (parent->_color == RED) //如果父亲结点是红色结点
{
if ((subLL == NULL&&subLR == NULL)||
(subLL&&subLR&&subLL->_color == BLACK&&subLR->_color == BLACK))
{
parent->_color = BLACK; //让cur这条路径上的黑色接点增加一个
subL->_color = RED; //subL这条路径上的黑色接点个数不变
break;
}
}
if (subLR->_color == RED) //subL的右孩子为红,先对subL进行左旋
{
//将双旋变为右单旋的情况
RotateL(subL);
subL = subLR; //让subL指向旋转之后的父节点
}
RotateR(parent); //对parent进行右单旋
//将旋转之后新的父节点subL变为parent的颜色
if (parent->_color == RED)
subL->_color = RED;
else
subL->_color = BLACK;
parent->_color = BLACK;
subL->_left->_color = BLACK;
break;
}
}
}
}
_root->_color = BLACK;
delete del;
return true;
}
bool IsBlance()
{
if (_root == NULL) //如果是空树,则就是平衡的
return true;
if (_root->_color == RED) //如果树的根节点是红色的,则这棵树就不是平衡的
return false;
int count = 0;
//用count统计这棵树最左路中黑色结点的个数,作为与其他路径比较的基准
Node* cur = _root;
while (cur)
{
if (cur->_color == BLACK)
count++;
cur = cur->_left;
}
int num=0;
return _IsBlance(_root,num,count);
}
protected:
bool _IsBlance(Node* root,int num,const int& count)
{
if (root == NULL)
{
return num==count;
}
//如果这个结点是红色的,就去判断他的父亲是什么颜色,如果这个结点是红色的,则它一定不是根节点
if (root->_color == RED&&root->_parent->_color==RED)
return false;
if (root->_color == BLACK)
num++;
return _IsBlance(root->_left,num,count)&&_IsBlance(root->_right,num,count);
}
void _Copy(Node* root,Node* &newroot)
{
if (root == NULL)
return;
Node* cur = new Node(root->_key,root->_value);
cur->_color = root->_color;
newroot = cur;
cur->_parent = newroot;
_Copy(root->_left,cur->_left);
_Copy(root->_right,cur->_right);
}
void _Destory(Node* root)
{
if (root == NULL)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
}
void RotateL(Node* parent) //左旋
{
Node* ppNode = parent->_parent;
Node* subR = parent->_right;
parent->_right = subR->_left;
if (subR->_left)
subR->_left->_parent = parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == NULL)
{
_root = subR;
_root->_parent = NULL;
}
else
{ //与上层进行链接
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
void RotateR(Node* parent) //右旋
{
Node* ppNode = parent->_parent;
Node* subL = parent->_left;
parent->_left = subL->_right;
if (subL->_right)
subL->_right->_parent = parent;
subL->_right = parent;
parent->_parent = subL;
if (ppNode == NULL)
{
_root = subL;
_root->_parent= NULL;
}
else //与上层结点链接
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
private:
Node* _root;
};标签:return 左旋转 期望 type users swa 最长路 user 删除算法
原文地址:http://blog.csdn.net/lf_2016/article/details/52974143