Algorithm: 红黑树

红黑树

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

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;
			
		}
	}
} 

 

    原文作者:红黑树
    原文地址: https://my.oschina.net/SHIHUAMarryMe/blog/711468
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞