红黑树(三) 之 C++ STL模板实现(完整源码)


本文章主要是C++实现红黑树的代码,如果想了解红黑树的原理及其算法的详细介绍。
请去看另一篇文章: 红黑树(一)的原理和算法详细介绍


一、R-B Tree简介

R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。

红黑树的特性(规则):

(1)每个节点或者是黑色(Black),或者是红色(Red)。
(2)根节点是黑色(Black)。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NILNULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

注意:
(01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
(02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。

因此,满足以上五条特性的二叉树就叫做红黑树。

红黑树示意图如下:
建议根据以上红黑树的五条特性查看:
在这里插入图片描述

二、C++完整源码

红黑树完整源代码

#include <iostream>
#include <string>
#include <memory>
#include <array>
#include <vector>
#include <stack>
#include <queue>

//颜色枚举类型
enum RBColor{RED,BlACK};

//泛型模板  //红黑树的Node类
template <class T>
class RBTNode{
public:
	T key;          //键值
	RBColor color;  //颜色
	RBTNode* lChild;//左孩子节点 
	RBTNode* rChild;//右孩子节点
	RBTNode* parent;//父亲节点
	
	RBTNode() = default;
	
	RBTNode(T k, RBColor c, RBTNode* l, RBTNode* r, RBTNode* p):key(k),color(c),lChild(l),rChild(r),parent(p){}
	
};

//泛型模板
template <class T>
class RBTree{
private:
	RBTNode<T>* root; //根节点
	
public:
	RBTree(){}
	~RBTree(){}
	
	//获取父亲节点
	RBTNode<T>* parentOf(RBTNode<T>* p);
	//获取颜色
	RBColor colorOf(RBTNode<T>* p);
	//设置父亲节点
	void setParent(RBTNode<T>* p, RBTNode<T>* pp);
	//设置颜色
	void setColor(RBTNode<T>* p,RBColor c);
	
	//判断是否是红色
	bool isRed(RBTNode<T>* p);
	//判断是否是黑色
	bool isBlack(RBTNode<T>* p);
	//设置为红色
	void setRed(RBTNode<T>* p);
	//设置为黑色
	void setBlack(RBTNode<T>* p);
	
	
	//搜索查询节点是否存在
	RBTNode<T>* search(T key);
	//后继最小左节点
	RBTNode<T>* min(RBTNode<T>* p);
	//找到后继节点
	RBTNode<T>* successor(RBTNode<T>* p);
	
	//添加
	void insert(T key);
	//删除
	void remove(T key);
	
	// 前序遍历"红黑树"
	void preOrder();
	// 中序遍历"红黑树"
	void inOrder();
	// 后序遍历"红黑树"
	void postOrder();
	// 层序遍历"红黑树"
	void levelorder();
	
private:
	//左旋
	void leftRotate(RBTNode<T>* p); 
	//右旋
	void rightRotate(RBTNode<T>* p); 
	
	//插入
	void insert(RBTNode<T>* node);
	//插入修正
	void insertFixUp(RBTNode<T>* node);
	
	//删除
	void remove(RBTNode<T>* node);
	//删除修正
	void removeFixUp(RBTNode<T>* node,RBTNode<T>* parent);
	
};


//类函数的实现

//获取父亲节点
template <class T>
RBTNode<T>* RBTree<T>::parentOf(RBTNode<T>* p){
	if(p != NULL){
		return p->parent;
	}
	
	return NULL;
}

//获取颜色
template <class T>
RBColor RBTree<T>::colorOf(RBTNode<T>* p){
	if(p != NULL){
		return p->color;
	}	
	
	return BlACK;
}

//设置父亲节点
template <class T>
void RBTree<T>::setParent(RBTNode<T>* p, RBTNode<T>* pp){
	if(p != NULL){
		p->parent = pp;
	}
	
}

//设置颜色
template <class T>
void RBTree<T>::setColor(RBTNode<T>* p,RBColor c){
	if(p != NULL){
		p->color = c;
	}
	
}


//判断是否是红色
template <class T>
bool RBTree<T>::isRed(RBTNode<T>* p){
	
	return p != NULL && p->color == RED ? true : false ;
}

//判断是否是黑色
template <class T>
bool RBTree<T>::isBlack(RBTNode<T>* p){
	
	return p == NULL || p->color == BlACK ? true : false ;
}

//设置为红色
template <class T>
void RBTree<T>::setRed(RBTNode<T>* p){
	if(p != NULL){
		p->color = RED;
	}
}

//设置为黑色
template <class T>
void RBTree<T>::setBlack(RBTNode<T>* p){
	if(p != NULL){
		p->color = BlACK;
	}
}


//搜索查询节点是否存在
template <class T>
RBTNode<T>* RBTree<T>::search(T key){
	RBTNode<T>* node = this->root;
	//根节点不为空
	while(node != NULL){
		if(key < node->key){
			node = node->lChild;
		}else if(key > node->key){
			node = node->rChild;
		}else{
			
			return node;
		}
		
		
	}
	
	return NULL;
}

//后继最小左节点
template <class T>
RBTNode<T>* RBTree<T>::min(RBTNode<T>* p){
	if(p->lChild == NULL){
		return p;
	}
	
	while(p->lChild != NULL){
		p = p->lChild;
	}
	
	return p;
}

//找到后继节点
template <class T>
RBTNode<T>* RBTree<T>::successor(RBTNode<T>* p){
	if(p->rChild != NULL){
		return min(p->rChild);
	}
	
	return NULL;
}


//左旋
template <class T>
void RBTree<T>::leftRotate(RBTNode<T>* p){
	RBTNode<T>* x = p->rChild;
	
	p->rChild = x->lChild;
	
	if(x->lChild != NULL){
		setParent(x->lChild,p);
	}
	
	setParent(x , p->parent);
	
	if(p->parent != NULL){
		if(p->parent->lChild == p){
			p->parent->lChild = x;
		}else{
			p->parent->rChild = x;
		}
		
	}else{
		
		this->root = x;
	}
	
	x->lChild = p;
	p->parent = x;
	
}

//右旋
template <class T>
void RBTree<T>::rightRotate(RBTNode<T>* p){
	RBTNode<T>* y = p->lChild;
	
	p->lChild = y->rChild;
	
	if(y->rChild != NULL){
		setParent(y->rChild,p);
	}
	
	setParent(y , p->parent);
	
	if(p->parent != NULL){
		if(p->parent->lChild == p){
			p->parent->lChild = y;
		}else{
			p->parent->rChild = y;
		}
		
	}else{
		
		this->root = y;
	}
	
	y->rChild = p;
	p->parent = y;
	
}

//插入修正
template <class T>
void RBTree<T>::insertFixUp(RBTNode<T>* node){
	
	RBTNode<T>* parent,*gparent,*uncle;
	
	while((parent = parentOf(node)) && isRed(parent)){
		
		gparent = parentOf(parent);
		
		if(gparent->lChild == parent){
			
			uncle = gparent->rChild;
			
			//Case 1条件: 叔叔节点是红色
			if(uncle != NULL && isRed(uncle)){
				
				//操作
				setBlack(parent);
				setBlack(uncle);
				setRed(gparent);
				
				node = gparent;
				
				continue;
			}else{
				//Case 2条件: 叔叔节点是黑色,且当前节点是父亲节点的右孩子
				if(parent->rChild == node){
					
					//操作
					leftRotate(parent);
					RBTNode<T>* tmp = parent;
					parent = node;
					node = tmp;
					
				}
				
				//Case 3条件: 叔叔节点是黑色,且当前节点是父亲节点的左孩子
				
				//操作
				setBlack(parent);
				setRed(gparent);
				rightRotate(gparent);
				
			}
			
		}else{  //同理(左右相反)
			
			uncle = gparent->lChild;
			
			//Case 1条件: 叔叔节点是红色
			if(uncle != NULL && isRed(uncle)){
				
				//操作
				setBlack(parent);
				setBlack(uncle);
				setRed(gparent);
				
				node = gparent;
				
				continue;
			}else{
				//Case 2条件: 叔叔节点是黑色,且当前节点是父亲节点的左孩子
				if(parent->lChild == node){
					
					//操作
					rightRotate(parent);
					RBTNode<T>* tmp = parent;
					parent = node;
					node = tmp;
					
				}
				
				//Case 3条件: 叔叔节点是黑色,且当前节点是父亲节点的右孩子
				
				//操作
				setBlack(parent);
				setRed(gparent);
				leftRotate(gparent);
				
			}
			
		}
		
	}
	
	//根节点总是设为黑色
	if(this->root == node){
		setBlack(node);
	}
	
}



//插入
template <class T>
void RBTree<T>::insert(RBTNode<T>* node){
	RBTNode<T>* mroot = this->root;
	RBTNode<T>* mrootParent = NULL;
	
	while(mroot != NULL){
		mrootParent = mroot;
		
		if(node->key < mroot->key){
			mroot = mroot->lChild;
		}else{
			mroot = mroot->rChild;
		}
	}
	
	node->parent = mrootParent;
	
	if(mrootParent != NULL){
		if(node->key < mrootParent->key){
			mrootParent->lChild = node;
		}else{
			mrootParent->rChild = node;
		}
		
	}else{
		this->root = node;
	}
	
	//每次插入的节点总是设置为红色
	setRed(node);
	
	//总是进入插入修正算法
	insertFixUp(node);
	
	
}

//添加键值
template <class T>
void RBTree<T>::insert(T key){
	RBTNode<T>* node = NULL;
	
	node = new RBTNode<T>(key,BlACK,NULL,NULL,NULL);
	
	std::cout<<"成功添加["<< node->key<<"]值" <<std::endl;
	
	if(node != NULL){
		insert(node);
	}
	
}


//移除节点后进行修正
template <class T>
void RBTree<T>::removeFixUp(RBTNode<T>* node,RBTNode<T>* parent){
	//保存替换节点的兄弟节点
	RBTNode<T>* other;
	
	while((node == NULL || isBlack(node)) && this->root != node){
		
		//获取替换节点的兄弟节点
		if(parent->lChild == node){
			
			other = parent->rChild;
			
			std::cout<<"当前父亲节点parent:"<<parent->key<<"  other兄弟节点"<<other->key<< std::endl;
			
			// Case 1: node的兄弟节点是红色的 
			if(other != NULL && isRed(other)){
				
				std::cout<<"Case 1: node的兄弟节点是红色的 "<<std::endl;
				
				//操作
				setBlack(other);
				setRed(parent);
				leftRotate(parent);
				
				other = parent->rChild;
				
				continue;
			}else{
				
				// Case 2: node的兄弟节点是黑色,且兄弟节点的左右孩子节点都为黑色  
				if((other->lChild == NULL || isBlack(other->lChild)) && 
					(other->rChild == NULL || isBlack(other->rChild))){
					
					std::cout<<"Case 2: node的兄弟节点是黑色,且兄弟节点的左右孩子节点都为黑色 "<<std::endl;
					
					//操作
					setRed(other);
					node = parent;
					parent = parentOf(node);
					
					continue;
				}else{
					
					// Case 3: node的兄弟节点是黑色,且兄弟节点的左孩子节点为红色,右孩子节点为黑色  
					if(isRed(other->lChild) && (other->rChild == NULL || isBlack(other->rChild))){
						
						std::cout<<"Case 3: node的兄弟节点是黑色,且兄弟节点的左孩子节点为红色,右孩子节点为黑色"<<std::endl;
						
						//操作
						setBlack(other->lChild);
						setRed(other);
						rightRotate(other);
						
						other = parent->rChild;
						
						
					}
					
					// Case 4: node的兄弟节点是黑色,且兄弟节点的右孩子节点为红色,左孩子节点颜色随意
					std::cout<<"Case 4: node的兄弟节点是黑色,且兄弟节点的右孩子节点为红色,左孩子节点颜色随意"<<std::endl;
					
					
					//操作
					setColor(other, colorOf(parent));
					setBlack(parent);
					setBlack(other->rChild);
					leftRotate(parent);
					
					node = this->root;
					
					break;
				}
				
			}	
			
		}else{  //同理(左右相反)
			
			other = parent->lChild;
			
			std::cout<<"当前父亲节点parent:"<<parent->key<<"  other兄弟节点"<<other->key<< std::endl;
			
			// Case 1: node的兄弟节点是红色的 
			if(other != NULL || isRed(other)){
				
				std::cout<<"Case 1: node的兄弟节点是红色的 "<<std::endl;
				
				//操作
				setBlack(other);
				setRed(parent);
				rightRotate(parent);
				
				other = parent->lChild;
				
				continue;
			}else{
				
				// Case 2: node的兄弟节点是黑色,且兄弟节点的左右孩子节点都为黑色  
				if((other->lChild == NULL || isBlack(other->lChild)) && 
					(other->rChild == NULL || isBlack(other->rChild))){
					
					std::cout<<"Case 2: node的兄弟节点是黑色,且兄弟节点的左右孩子节点都为黑色 "<<std::endl;
					
					//操作
					setRed(other);
					node = parent;
					parent = parentOf(node);
					
					continue;
				}else{
					
					// Case 3: node的兄弟节点是黑色,且兄弟节点的右孩子节点为红色,左孩子节点为黑色  
					if(isRed(other->lChild) && (other->rChild == NULL || isBlack(other->rChild))){
						
						std::cout<<"Case 3: node的兄弟节点是黑色,且兄弟节点的右孩子节点为红色,左孩子节点为黑色"<<std::endl;
						
						//操作
						setBlack(other->rChild);
						setRed(other);
						leftRotate(other);
						
						other = parent->lChild;
						
						
					}
					
					// Case 4: node的兄弟节点是黑色,且兄弟节点的左孩子节点为红色,右孩子节点颜色随意
					std::cout<<"Case 4: node的兄弟节点是黑色,且兄弟节点的左孩子节点为红色,右孩子节点颜色随意"<<std::endl;
					
					
					//操作
					setColor(other, colorOf(parent));
					setBlack(parent);
					setBlack(other->lChild);
					rightRotate(parent);
					
					node = this->root;
					
					break;
				}
				
			}	

			
		}
		
	}
	
	if(node != NULL){
		setBlack(node);
		std::cout<<"当前node节点"<<node->key<<"染黑!!!"<<std::endl;
	}
	
	std::cout<<"删除修正,红黑树调整完成!!!"<<std::endl;
	
}


//移除节点
template <class T>
void RBTree<T>::remove(RBTNode<T>* node){
	//孩子节点和父亲节点要进入删除修正算法和替换节点
	RBTNode<T>* child,*parent,*replace;
	
	RBColor color = BlACK; //颜色判断
	
	//分几种情况进入
	//待删除节点的左右孩子节点非空
	if(node->lChild != NULL && node->rChild != NULL){
		
		//寻找待删除节点的后继节点(替换节点)
		replace = successor(node);
		
		//获取待删除节点的父亲节点
		parent = parentOf(replace);
		
		//因为替换节点是最小节点,所以它要不左右节点非空或只有右孩子节点
		child = replace->rChild;
		
		//因为实际上是删除的替换节点的颜色
		color = colorOf(replace);
		
		//如果替换节点的父亲节点是待删除节点
		if(parentOf(replace) == node){
			parent = replace;
			
		}else{
			
			if(child != NULL){
				setParent(child,parentOf(replace));
			}
			
			replace->parent->lChild = child;
			
			replace->rChild = node->rChild;
			setParent(node->rChild,replace);
			
		}
		
		setParent(replace,parentOf(node));
		
		replace->lChild = node->lChild;
		setParent(node->lChild,replace);
		
		//设置颜色
		setColor(replace,colorOf(node));
		
		if(node->parent == NULL){
			this->root = replace;
		}else{
			if(node->parent->lChild == node){
				node->parent->lChild = replace;
			}else{
				node->parent->rChild = replace;
			}
		}
		
		
		//符合条件进入修正
		if(color == BlACK){
			//总是进入修正
			removeFixUp(child,parent);
		}
		
		//删除该节点所占用的内存空间
		delete node;
		
		return ;
		
	}else{  //只有一个节点或者无节点的情况下
		
		if(node->lChild != NULL){
			replace = node->lChild;
		}else{
			replace = node->rChild;
		}
		
		parent = parentOf(node);
		
		if(parent != NULL){
			if(parent->lChild == node){
				parent->lChild = replace;
			}else{
				parent->rChild = replace;
			}
		}else{
			this->root = replace;
		}
		
		
		setParent(replace,parent);
		
		color = colorOf(node);
		
		child = replace;
		
		//删除该节点所占用的内存空间
		delete node;
		
		//符合条件进入修正
		if(color == BlACK){
			//总会进入修正算法
			removeFixUp(child,parent);
		}
		
	}
	
	
}


//删除
template <class T>
void RBTree<T>::remove(T key){
	RBTNode<T>* node = NULL;
	if((node = search(key)) != NULL){
		
		remove(node);
	}
	
}




// 层序遍历"红黑树"
template <class T>
void RBTree<T>::levelorder(){
	if(this->root == NULL)return;
	
	RBTNode<T>* cur = this->root;
	
	std::string col = "moren";
	
	std::queue<RBTNode<T>*> que;
	
	while(!que.empty() || cur != NULL){
		while(cur != NULL){
			que.push(cur);
			cur = cur->lChild;
		}
		
		RBTNode<T>* node = que.front();
		que.pop();
		//st.pop();
		if(isBlack(node)){
			col =  "BLACK";
		}else{
			col =  "RED";
		}
		
		if(node->parent == NULL){
			std::cout<< "根节点:"<<node->key<<" : "<<col<<"  父节点:NULL" <<std::endl;
		}else{
			std::cout<<node->key<<" : "<<col<<"  父节点:"<< node->parent->key <<std::endl;
		}
		
		
		if(node->rChild != NULL){
			cur = node->rChild;
		}
		
	}
	
}



//在main()函数中进行红黑树的测试数据

int main(){
	
	RBTree<int> tree {};
	
	std::array arr = {10, 40, 30, 60, 90, 70, 20, 50, 80,120,150,110,100,130,140};
	
	std::cout<<"原始值:"<<std::endl;
	for(int i=0;i<arr.size();i++){
		std::cout<<arr[i]<<" ";
	}
	
	std::cout<<std::endl;
	
	for(int i : arr){
	
		tree.insert(i);
	}
	std::cout<<std::endl;
	
	std::cout<<"红黑树的层序遍历:"<<std::endl;
	tree.levelorder();
	std::cout<<std::endl;
	
	
	tree.remove(60);
	std::cout<<std::endl;
	
	std::cout<<"删除后:"<<std::endl;
	std::cout<<std::endl;
	
	std::cout<<"红黑树的层序遍历:"<<std::endl;
	tree.levelorder();
	
	
	
	
	return 0;
}

运行结果截图:
在这里插入图片描述
在这里插入图片描述
直接复制粘贴代码到支持C++的ide编辑器中直接运行就可以,很方便!!!


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿文佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值