您的位置:首页 > 编程语言 > Go语言

Algorithm: 红黑树

2016-07-14 00:00 399 查看
摘要: 逐步完善

红黑树
一棵红黑树是满足下面性质的二叉搜索树:

1,每个结点或是红色,或是黑色的.

2,根节点必须是黑色的.

3,每个分支的最后一个结点是黑色.

4,如果一个结点是红色的,则它的两个子结点必然都是黑色.

5,对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点.

#include <iostream>
#include <memory>
#include <type_traits>

//注明:以nullptr表示树的尾部.

enum class Color : int{
Red,
Black
};

template<typename T>
class Node{
public:
T data;
Color color;
Node<T>* left;
Node<T>* right;
Node<T>* parent;

public:
Node(Color clir = Color::Black):color(clr),parent(nullptr),left(nullptr),right(nullptr){}

template<typename Ty>
Node(const Ty& dt, Color clr = Color::Black, Node<T>* lh=nullptr, Node<T>* rh=nullptr, Node<T>* pr=nullptr);

Node(const T& dt, Color clr=Color::Black, Node<T>* lh=nullptr, Node<T>* rh=nullptr, Node<T>* pr=nullptr);

~Node()=default;
};

template<typename T>
template<typename Ty>
Node<T>::Node(const Ty& dt, Color clr, Node<T>* lh, Node<T>* rh, Node<T>* pr)
:data(dt),
color(clr),
left(lh),
right(rh),
parent(pr)
{
//
}

template<typename T>
Node<T>::Node(const T& dt, Color clr, Node<T>* lh, Node<T>* rh, Node<T>* pr)
:data(dt),
color(clr),
left(lh),
right(rh),
parent(pr)
{
//
}

template<typename T>
class RBTree{
private:
Node<T>* root;

void leftRotate(Node<T>* rt, Node<T>* x); //在结点x上做左旋.

void rightRotate(Node<T>* rt, Node<T>* y); //右旋在结点y上做右旋.

void insertFixUp(Node<T>* rt, Node<T>* z); //插入修正保持红黑树的特性.

void transPlant(Node<T>* first, Node<T>* second); //辅助删除结点.

void deleteNode(Node<T>* node); //删除一个结点.

Node<T>* minmumSubNode(Node<T>* node); //返回node中最小的子结点.

void deleteFixUp(Node<T>* node); //删除修正,在删除一个红黑树结点后对红黑树进行修正保证红黑树的性质.

//----------辅助函数-----------
inline Node<T>* getParent(Node<T>* node)  //获得一个函数的父结点.
{
return node->parent;
}

inline Node<T>* getGParent(Node<T>* node);       //获得一个函数的父结点的父结点.
{
return (node->parent)->parent;
}

public:
template<typename ...Args>
RBTree(Args&&... parameters);

RBTree();

~RBTree();

};

//左旋:
template<typename T>
void RBTree<T>::leftRotate(Node<T>* rt, Node<T>* x)
{
Node<T>* y = x->right;
x->right = y->left;

if(y->left != nullptr){
y->left->parent = x;
}

y->parent = x->parent;

if(y->parent == nullptr){
rt = y;

}else if(x == x->parent->left){
x->parent->left = y;

}else{
x->parent->right = y;
}

y->left = x;
x->parent = y;
}

//                       7                                                               7
//                    /    \                                                          /     \
//                  4       11(x)                                                    4      18(y)
//                /    \     / \                  leftRotate(x)                     /     /      \
//              3       6   9  18(y)             --------------->                  3     11(x)    19
//             /              /  \               <---------------                 /     / \        \
//			 2              14    19              rightRotate(y)                 2     9   14      22
//                        /   \     \                                                     /  \    /
//                      12   17     22                                                  12   17  20
//                                 /
//                                20

//右旋:
template<typename T>
void RBTree<T>::rightRotate(Node<T>* rt, Node<T>* y)
{
Node<T>* x = y->left;
y->left = x->right;

if(x->right != nullptr){
x->right->parent = y;
}

x->parent = y->parent;

if(y->parent == nullptr){
rt = x;

}else if(y == y->parent->left){
y->parent->left  = y;

}else{
y->parent->left = x;
}

x->right = y;
y->parent = x;
}

//插入修正.
template<typename T>
void RBTree<T>::insertFixUp(Node<T>* rt, Node<T>* z)
{
Node<T>* zParent = (this->getParent)(z);
Node<T>* zGParent = (this->getGParent)(z);

while(zParent->color == Color::Red){

if(zParent == zGParent->left){
Node<T>* y = zGParent->right;

if(y->color == Color::Red){
zParent->color = Color::Black;
y->color = Color::Black;
zGParent->color = Color::Red;

z = zGParent;
zParent = (this->getParent)(z);
zGParent = (this->getGParent)(z);

}else if(z == zParent->right){
z = (this->getParent)(z);
this->leftRotate(rt, z);
}

(this->getParent)(z)->color = Color::Black;
(this->getGParent)(z)->color = Color::Red;
this->rightRotate(rt, this->getGParent(z));

}else if(zParent == zGParent->right){
Node<T>* y = zGParent->left;

if(y->color == Color::Red){
zParent->color = Color::Black;
y->color = Color::Blac;
zGParent->color = Color::Red;

z = zGParent;
zParent = (this->getParent)(z);
zGParent = (this->getGParent)(z);

}else if(z == zParent->left){
z = (this->getParent)(z);
this->rightRotate(rt, z);

}

(this->getParent)(z)->color = Color::Black;
(this->getGParent)(z)->color = Color::Red;
this->rightRotate(rt, this->getGParent(z));
}
}

rt->color = Color::Black;
}

//辅助删除结点. 借鉴了二叉搜索树的transPlant.
//1, 如果first结点是树根,那么就更新红黑树的根结点为.
//2, 如果first为其父结点的左结点的情况.
//3, 如果fist为其父亲右结点的情况.
template<typename T>
void RBTree<T>::transPlant(Node<T>* first, Node<T>* second)
{
if(first->parent == nullptr){
this->root = first;

}else if(first == first->parent->left){
first->parent->left = second;

}else{
first->parent->right = second;
}

first->parent = second->parent;
}

//辅助删除结点. 借鉴了二叉搜索树的minmum.
//主要作用是把被删除的结点的2个子结点连接到被删除结点的父结点下面.
template<typename T>
Node<T>* RBTree<T>::minimumSubNode(Node<T>* node)
{
Node<T> tempNode = nullptr;

if(node != nullptr){
while(node->left != nullptr){
tempNode = node->left;
}
}

return tempNode;
}

//删除一个结点.
template<typename T>
void RBTree<T>::deleteNode(Node<T>* node)
{
Node<T>* tempNodeOne = node;
Node<T>* tempNodeTwo = nullptr;

Color tempColor = tempNode->color;

if(node->left == nullptr){
tempNodeTwo = node->right;
this->transPlant(node, node->right);

}else if(node->right == nullptr){
tempNodeTwo = node->left;
this->transPlant(node, node->left);

}else{
tempNodeOne = minimumSubNode(node->right);
tempColor = tempNodeOne->color;
tempNodeTwo = tempNodeOne->right;

if(tempNodeOne->parent == node){
tempNodeTwo->parent = tempNodeOne;

}else{
this->transPlant(tempNodeOne, tempNodeOne->right);
tempNodeOne->right = node->right;
tempNodeOne->right->parent = tempNodeOne;
}

this->transPlant(node, tempNodeOne);
tempNodeOne->left = node->left;
tempNodeOne->left->parent = tempNodeOne;
tempNodeOne->color = node->color;

}

if(tempColor == Color::Black){

}
}

//用于在删除一个结点过后修正红黑树的性质.
template<typename T>
void RBTree<T>::deleteFixUp(Node<T>* node)
{
Node<T>* tempNodeOne = nullptr;

while(x != this->root && node->color == Color::Black){

if(node == node->parent->left){
tempNodeOne = node->parent->right;

//case 1:
if(tempNodeOne->color == Color::Red){
tempNodeOne->color = Black;

this->leftRotate(this->root, node->parent);// notice! left-rotate!

tempNodeOne = node->parent->right;

}

//case 2:
if(tempNodeOne->left->color == Color::Black && tempNodeOne->right->color == Black){
tempNodeOne->color = Color::Red;
node = node->parent;

//case 3:
}else if(tempNodeOne->right->color == Color::Black){
tempNodeOne->left->color = Color::Black;
tempNodeOne->color = Color::Red;
this->rightRotate(this->root, tempNodeOne);
tempNodeOne = node->parent->right;
}

}else{
tempNodeOne = node->parent->left;

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: