栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++实现红黑树

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++实现红黑树

1.红黑树的基本概念

 2.节点的定义

// 基本定义
enum RBTColor{RED, BLACK};
template
class RBTNode{
public:
	RBTColor color; // 颜色
	T key; // 键值 
	RBTNode* left; // 左孩子
	RBTNode* right; // 右孩子
	RBTNode* parent; // 父节点
	RBTNode(T value, RBTColor c, RBTNode* p, RBTNode* l, RBTNode* r):
		key(value),color(c),parent(p),left(l),right(r){
	} 
};

3.红黑树类的定义

template
class RBTree{
private:
	RBTNode* mRoot;
public:
	RBTree();
	~RBTree();
	// 前序遍历
	void preOrder();
	// 中序遍历 
	void inOrder();
	// 后序遍历 
	void postOrder();
	RBTNode* iterativeSearch(T key);
	// (递归实现)查找”红黑树“中键值为key的节点
	RBTNode* search(T key); 
	// 查找最小节点:返回最小节点的键值
	T minimum();
	// 查找最大节点:返回最大节点的键值
	T maximum(); 
	// 将节点(key为节点键值)插入到红黑树中
	void insert(T key);
	// 删除节点(key为节点键值)
	void remove(T key);
	// 销毁红黑树
	void destroy();
	// 打印红黑树
	void print(); 
private:
	// 前序遍历”红黑树“
	void preOrder(RBTNode* tree) const;
	// 中序遍历”红黑树“ 
	void inOrder(RBTNode* tree) const;
	// 后续遍历“红黑树” 
	void postOrder(RBTNode* tree) const;
	// (递归实现)查找”红黑树“中键值为key的节点
	RBTNode* search(RBTNode* x ,T key) const;
	// (非递归实现)查找”红黑树“中键值为key的节点
	RBTNode* iterativeSearch(RBTNode* x ,T key) const;  
	// 查找最小节点:返回最小节点的键值
	RBTNode* minimum(RBTNode* tree);
	// 查找最大节点:返回最大节点的键值
	RBTNode* maximum(RBTNode* tree);
	// 查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点 
	RBTNode* successor(RBTNode* x); 
	// 查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点 
	RBTNode* predecessor(RBTNode* x);   
	// 左旋
	void leftRotate(RBTNode* &root, RBTNode* x);
	// 右旋
	void rightRotate(RBTNode* &root, RBTNode* y);
	// 插入函数
	void insert(RBTNode*&root, RBTNode* node);
	// 插入修正函数
//	void insertFixUp(RBTNode*&root, RBTNode* node, RBTNode* parent);
	void insertFixUp(RBTNode*&root, RBTNode* node);
	// 删除的修正函数 
	void removeFixUp(RBTNode*&root, RBTNode* node, RBTNode* parent);
	// 查找需要替代删除的节点 
	RBTNode* findReplaceNode(RBTNode* node);
	// 销毁红黑树
	void destroy(RBTNode* &tree);
	// 打印红黑树
	void print(RBTNode* &tree, T key, int direction); 

#define rb_parent(r) ((r)->parent)
#define rb_color(r) ((r)->color)
#define rb_is_red(r) ((r)->color == RED)
#define rb_is_black(r) ((r)->color == BLACK)
#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
#define rb_set_red(r) do{(r)->color = RED;}while(0)
#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
#define rb_set_color(r,c) do{(r)->color = (c);}while(0)
};

4.红黑树中几个主要的算法解析

4.1前驱算法思路

查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点 。

如上图所示,节点值为10的前驱应该是以其左孩子为根节点的子树中的最大值节点,即节点值为8。查找思路:若查找节点X的前驱,则先移动到X的左孩子(X->left),再一直查找右孩子直到右孩子为空。

4.2后继算法思路

查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点 

如上图所示,节点值为10的后继节点应该是以其右孩子为根节点的子树中的最小值节点,即节点值为11。查找思路:若查找节点X的后继,则先移动到X的右孩子(X->right),再一直查找左孩子直到左孩子为空。

4.3插入算法思路

(1)插入的节点若是根节点,则直接染黑

 (2)插入的节点X(不管是左孩子还是右孩子)的父节点P为黑色,则不用操作

(3)L为P的左孩子,若新插入的节点X的父节点L和叔叔节点R都是红色,则将L和R染黑,P染红,再将P作为新插入的节点继续向上判断 

 (4)L为P的左孩子,若插入的节点X的父节点L为红色且X为L的左孩子,叔叔节点R为黑色,则根据P右旋,将L染黑,P染红

(5)若插入节点X为父节点L的右孩子,且L为红色,叔叔节点R为黑色,则先根据L左转,再根据P右转,将X染黑,P染红

(6)R为P的右孩子,若插入的节点X的父节点R为红色且X为L的右孩子,叔叔节点L为黑色,则根据P左旋,将R染黑,P染红

(7)R为P的右节点,若插入节点X为父节点R的左孩子,且R为红色,叔叔节点L为黑色,则先根据R右转,再根据P左转,将X染黑,P染红

4.4删除算法思路

删除节点方案:

1.找到前驱节点,复制前驱节点值覆盖预备删除的节点的值,然后删除前驱节点

2.找到后继节点,复制后继节点值覆盖预备删除的节点的值,然后删除后继节点

通过前驱节点与后继节点的替换,可以将删除的节点转移到叶子节点上,方便操作

蓝色节点表示红或者黑,下面删除的节点都是以删除节点x为例

(1)删除节点x为红色,不管是父节点的左孩子还是右孩子,则直接删除

(2)删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色 

 (3)节点X与Y为黑色,且节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,需要先根据Y右旋,再据P左旋,将L变为P的颜色,再将P染黑

 (4)节点X与Y为黑色,节点X的兄弟节点Y,只包含右孩子R且为红色,则删除节点X后,据P左旋,再将Y变为P的颜色,将P和R染黑。

 (5)节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,再根据P进行左旋,再将Y变为P的颜色,P和R变黑

​​​​

(6)被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比为黑色。删除节点X,在根据P进行左旋,再将Y染黑,L染红

4.5红黑树代码

有点大800行左右

#include
#include 
using namespace std;

// 基本定义
enum RBTColor{RED, BLACK};
template
class RBTNode{
public:
	RBTColor color; // 颜色
	T key; // 键值 
	RBTNode* left; // 左孩子
	RBTNode* right; // 右孩子
	RBTNode* parent; // 父节点
	RBTNode(T value, RBTColor c, RBTNode* p, RBTNode* l, RBTNode* r):
		key(value),color(c),parent(p),left(l),right(r){
	} 
};
template
class RBTree{
private:
	RBTNode* mRoot;
public:
	RBTree();
	~RBTree();
	// 前序遍历
	void preOrder();
	// 中序遍历 
	void inOrder();
	// 后序遍历 
	void postOrder();
	RBTNode* iterativeSearch(T key);
	// (递归实现)查找”红黑树“中键值为key的节点
	RBTNode* search(T key); 
	// 查找最小节点:返回最小节点的键值
	T minimum();
	// 查找最大节点:返回最大节点的键值
	T maximum(); 
	// 将节点(key为节点键值)插入到红黑树中
	void insert(T key);
	// 删除节点(key为节点键值)
	void remove(T key);
	// 销毁红黑树
	void destroy();
	// 打印红黑树
	void print(); 
private:
	// 前序遍历”红黑树“
	void preOrder(RBTNode* tree) const;
	// 中序遍历”红黑树“ 
	void inOrder(RBTNode* tree) const;
	// 后续遍历“红黑树” 
	void postOrder(RBTNode* tree) const;
	// (递归实现)查找”红黑树“中键值为key的节点
	RBTNode* search(RBTNode* x ,T key) const;
	// (非递归实现)查找”红黑树“中键值为key的节点
	RBTNode* iterativeSearch(RBTNode* x ,T key) const;  
	// 查找最小节点:返回最小节点的键值
	RBTNode* minimum(RBTNode* tree);
	// 查找最大节点:返回最大节点的键值
	RBTNode* maximum(RBTNode* tree);
	// 查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点 
	RBTNode* successor(RBTNode* x); 
	// 查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点 
	RBTNode* predecessor(RBTNode* x);   
	// 左旋
	void leftRotate(RBTNode* &root, RBTNode* x);
	// 右旋
	void rightRotate(RBTNode* &root, RBTNode* y);
	// 插入函数
	void insert(RBTNode*&root, RBTNode* node);
	// 插入修正函数
//	void insertFixUp(RBTNode*&root, RBTNode* node, RBTNode* parent);
	void insertFixUp(RBTNode*&root, RBTNode* node);
	// 删除的修正函数 
	void removeFixUp(RBTNode*&root, RBTNode* node, RBTNode* parent);
	// 查找需要替代删除的节点 
	RBTNode* findReplaceNode(RBTNode* node);
	
	// 销毁红黑树
	void destroy(RBTNode* &tree);
	// 打印红黑树
	void print(RBTNode* &tree, T key, int direction); 

#define rb_parent(r) ((r)->parent)
#define rb_color(r) ((r)->color)
#define rb_is_red(r) ((r)->color == RED)
#define rb_is_black(r) ((r)->color == BLACK)
#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
#define rb_set_red(r) do{(r)->color = RED;}while(0)
#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
#define rb_set_color(r,c) do{(r)->color = (c);}while(0)	
};

template
RBTree::RBTree():mRoot(NULL){
	//mRoot = NULL;
}

template
RBTree::~RBTree(){
	destroy();
}

template
void RBTree::preOrder(RBTNode* tree) const{
	if(tree != NULL){
		cout << tree->key << " ";
		preOrder(tree->left);
		preOrder(tree->right);
	}
}
template
void RBTree::preOrder(){
	this->preOrder(mRoot);
}

template
void RBTree::inOrder(RBTNode* tree) const{
	if(tree != NULL){
		inOrder(tree->left);
		cout << tree->key << " ";
		inOrder(tree->right);
	}
}
template
void RBTree::inOrder(){
	this->inOrder(mRoot);
}

template
void RBTree::postOrder(RBTNode* tree) const{
	if(tree != NULL){
		postOrder(tree->left);
		postOrder(tree->right);
		cout << tree->key << " ";
	}
}
template
void RBTree::postOrder(){
	this->postOrder(mRoot);
}
 
template
RBTNode* RBTree::search(RBTNode* x, T key) const{
	if(x == NULL || x->key == key){
		return x;
	}
	if(key < x->key){
		return search(x->left, key);
	}else{
		return search(x->right, key);
	}
} 
template
RBTNode* RBTree::search(T key){
	return search(mRoot, key);
}
// (非递归实现)查找”红黑树“中键值为key的节点
template
RBTNode* RBTree::iterativeSearch(RBTNode* x ,T key) const{
	while(x != NULL && x->key != key){
		if(key < x->key){
			return iterativeSearch(x->left, key);
		}else{
			return iterativeSearch(x->right, key);
		}
	}
	return x;
}
template
RBTNode* RBTree::iterativeSearch(T key){
	return iterativeSearch(mRoot, key);
}

template
RBTNode* RBTree::minimum(RBTNode* tree){
	if(tree == NULL){
		return NULL;
	}
	while(tree->left != NULL){
		tree = tree->left;
	}
	return tree;
}
template
T RBTree::minimum(){
	RBTNode* p = minimum(mRoot);
	if(p != NULL){
		return p->key;
	}
	return 0;
}

template
RBTNode* RBTree::maximum(RBTNode* tree){
	if(tree == NULL){
		return NULL;
	}
	while(tree->right != NULL){
		tree = tree->right;
	}
	return tree;
}
template
T RBTree::maximum(){
	RBTNode* p = maximum(mRoot);
	if(p != NULL){
		return p->key;
	}
	return 0;
}
 
template
RBTNode* RBTree::successor(RBTNode* x){
	// 如果x存在右孩子,则x的后继节点为其右孩子作为根节点子树的最小节点
	if(x->right != NULL){
		return minimum(x->right);
	} 
	// 如果x没有右孩子,则x有一下两种可能
	// 1.x是父节点的左孩子,则x的后继节点为父节点
	// 2.x是父节点的右孩子,则需要循环查找x的最低父节点,并且该父节点具有左孩子 
	RBTNode* y = x->parent;
	while(y != NULL && x != y->left){
			x = y;
			y = y->parent;
	}
	return y;
}
 
template
RBTNode* RBTree::predecessor(RBTNode* x){
	// 如果x存在左孩子,则x的后继节点为其右孩子作为根节点子树的最大节点
	if(x->left != NULL){
		return maximum(x->left);
	} 
	// 如果x没有左孩子,则x有一下两种可能
	// 1.x是父节点的右孩子,则x的后继节点为父节点
	// 2.x是父节点的左孩子,则需要循环查找x的最低父节点,并且该父节点具有右孩子 
	RBTNode* y = x->parent;
	while(y != NULL && x != y->right){
			x = y;
			y = y->parent;
	}
	return y;
}


template
void RBTree::leftRotate(RBTNode* &root, RBTNode* x){
	// 设置x的右孩子y
	RBTNode* y = x->right;
	// 将y的左孩子设为x的右孩子
	// 如果y的左孩子非空,将x设为y的左孩子的父亲
	x->right = y->left; 
	if(y->left != NULL){
		y->left->parent = x;
	}
	// 将x的父节点设置为y的父节点
	y->parent = x->parent;
	if(x->parent == NULL){
		root = y; // 如果x的父节点为空,则将y设为根节点 
	} else{
		if(x->parent->left == x){
			x->parent->left = y; // 如果x是他父节点的左孩子,则将y设为x的父节点的左孩子 
		}else{
			x->parent->right = y;// 如果x是他父节点的右孩子,则将y设为x的父节点的右孩子 
		}
	}
	// 将x设为y的左孩子
	y->left = x;
	// 将x的父节点设为y
	x->parent = y; 
}
 
template
void RBTree::rightRotate(RBTNode* &root, RBTNode* y){
	// 获取节点x 
	RBTNode* x = y->left;
	// 如果x的右孩子非空,则将x的右孩子设置为y的左孩子
	y->left = x->right;
	if(x->right != NULL){
		x->right->parent = y;
	} 
	// 将x的父节点指向y的父节点 
	x->parent = y->parent;
	if(y->parent == NULL){
		root = x; // 如果y为根节点,则将x变为新的根节点 
	}else{
		if(y->parent->left == y){
			y->parent->left = x; // 如果y为父节点的左孩子,则将x设置为父节点的左孩子 
		}else{
			y->parent->right = x; // 如果y为父节点的右孩子,则将x设置为父节点的右孩子 
		}
	}
	y->parent = x; // 将y的父节点设置为x
	x->right = y;  // 将x的右孩子设置为y 	
}

//#define rb_parent(r) ((r)->parent)
//#define rb_color(r) ((r)->color)
//#define rb_is_red(r) ((r)->color == RED)
//#define rb_is_black(r) ((r)->color == BLACK)
//#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
//#define rb_set_red(r) do{(r)->color = RED;}while(0)
//#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
//#define rb_set_color(r,c) do{(r)->color = (c);}while(0)
 
template
void RBTree::insertFixUp(RBTNode*&root, RBTNode* node){
	// 定义父节点和祖父节点 
	RBTNode* parent;
	RBTNode* gparent;
	RBTNode* uncle;
	parent = rb_parent(node);
	// 1.插入位置为根,直接染黑
	if(parent == NULL){
		rb_set_black(node);
		root = node;
		return;
	}	
	// 2.父亲节点如果是黑色,则不需要染色或者旋转
	if(rb_is_black(parent)){
		return;
	} 
	RBTNode* curNode = node;
	parent = rb_parent(curNode);
	while(parent != NULL && rb_is_red(parent)){
		gparent = rb_parent(parent);
		// 先讨论父节点是祖父节点左孩子的情况 
		if(parent == gparent->left){
			uncle = gparent->right;
			if(uncle == NULL || rb_is_black(uncle)){
				if(curNode == parent->right){
					// 5.若插入节点为父节点的右孩子,且父节点为红色,叔叔节点为黑色,
					// 则先根据父节点左转,(再根据祖父右转,将当前染黑,祖父染红)跳转到4 	
					leftRotate(root, parent); 
					curNode = parent;
					parent = rb_parent(curNode);	
				}
				if(curNode == parent->left){
					// 4.父节点为祖父节点的左孩子,若插入的节点的父节点为红色且为父节点的左孩子,叔叔节点为黑色,
					// 则根据祖父节点右旋,将父节点染黑,祖父染红
					rightRotate(root, gparent); 
					rb_set_black(parent); // 将父节点染黑 
					rb_set_red(gparent);  // 将祖父节点染红 
					break;
				}
			}
		}// 父节点是祖父节点右孩子的情况 
		else{
			uncle = gparent->left;
			if(uncle == NULL || rb_is_black(uncle)){		
				if(curNode == parent->left){
					// 7.父节点为祖父节点的右孩子,若插入节点为父节点的左孩子,且父节点为红色,叔叔节点为黑色,
					// 则先根据父节点右转,(再根据祖父左转,将当前染黑,祖父染红)跳转到6
					rightRotate(root, parent); 
					curNode = parent;
					parent = rb_parent(curNode);	
				}
				if(curNode == parent->right){
					// 6.父节点为祖父节点的右孩子,若父节点为红色且插入节点为父节点的右孩子,叔叔节点为黑色,
					//则根据祖父左旋,将父节点染黑,祖父染红
					leftRotate(root, gparent); 
					rb_set_black(parent); // 将父节点染黑 
					rb_set_red(gparent);  // 将祖父节点染红 
					break;	
				}
			}
		}
		//3.父亲节点是红色,叔叔节点也是红色。父亲和叔叔节点染成黑色,
		//  爷爷染成红色,把爷爷看成新插入的节点,循环向上插入 
		if(uncle != NULL && rb_is_red(uncle)){
			rb_set_black(parent); // 将父节点染黑 
			rb_set_black(uncle);  // 将叔叔节点染黑 
			rb_set_red(gparent);  // 将祖父节点染红 
			curNode = gparent;
			parent = rb_parent(curNode);
		}
	}
	// 将根节点设为黑色
	rb_set_black(root); 
}
// 插入函数

template
void RBTree::insert(RBTNode*&root, RBTNode* node){
	RBTNode* y = NULL;
	RBTNode* x = root;
	// 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉树中
	while(x != NULL){
		y = x;
		if(node->key < x->key){
			x = x->left;
		}else{
			x = x->right;
		}
	} 
	node->parent = y;
	if(y != NULL){
		if(node->key < y->key){
			y->left = node;
		}else{
			y->right = node;
		}
	}else{
		root = node;
	}
	// 2.设置节点的颜色为红色
	node->color = RED;
	// 3.将它重新修正为一颗红黑树
	insertFixUp(root, node); 
}

template
void RBTree::insert(T key){
	RBTNode* z = NULL;
	// 如果新建节点失败,则返回
	if((z = new RBTNode(key, RED, NULL, NULL, NULL)) == NULL){
		return;
	} 
	insert(mRoot, z);
}

// 查找需要替代删除的节点 ,叶子节点即可 
template
RBTNode* RBTree::findReplaceNode(RBTNode* node){
	// 1.node本身就是叶子节点
	// 2.node存在左孩子或者右孩子
	RBTNode* curNode = node;
	RBTNode* preNode = node;
	while(curNode->left != NULL || curNode->right != NULL){
		// 先找后继节点 
		if(curNode->right != NULL){
			curNode = this->successor(curNode);
		}
		preNode->key = curNode->key;
		preNode = curNode;
		// 查找前驱节点 
		if(curNode->left != NULL){
			curNode = this->predecessor(curNode);
		}
		preNode->key = curNode->key;
		preNode = curNode;
	}
	return curNode; 
}
//#define rb_parent(r) ((r)->parent)
//#define rb_color(r) ((r)->color)
//#define rb_is_red(r) ((r)->color == RED)
//#define rb_is_black(r) ((r)->color == BLACK)
//#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
//#define rb_set_red(r) do{(r)->color = RED;}while(0)
//#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
//#define rb_set_color(r,c) do{(r)->color = (c);}while(0)

template
void RBTree::removeFixUp(RBTNode*&root, RBTNode* node, RBTNode* parent){
	RBTNode* x = this->findReplaceNode(node); // 将删除的节点转移到叶子节点 
	RBTNode* p = rb_parent(x);
	RBTNode* y = NULL;
	RBTNode* l = NULL; 
	RBTNode* r = NULL;
	// 先判断删除的叶子节点为父节点的左孩子情况 
	if(x == p->left){
		y = p->right; // x的兄弟节点
		if(y != NULL){
			l = y->left;
			r = y->right; 	
		}
		// 1. 删除节点为红色,不管是父节点的左孩子还是右孩子,则直接删除
		if(rb_is_red(x)){
			p->left = NULL;
			delete x;
		}// 2.删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色
		else if(y == NULL || (rb_is_black(x) && rb_is_black(y) && l == NULL && r == NULL)){
			p->left = NULL;
			delete x;
			rb_set_black(p);
			if(y != NULL){
				rb_set_red(y);
			}
		}// 3.节点x与Y为黑色,节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,需要先根据Y右旋,再据P左旋,将L变为P的颜色,
		 //再将P染黑
		else if(y != NULL && l != NULL && r == NULL && rb_is_red(l) && rb_is_black(x) && rb_is_black(y)){
			p->left = NULL;
			delete x;
			rightRotate(root, y); // 根据y右旋
			leftRotate(root, p); // 根据p左旋
			l->color = p->color;
			rb_set_black(p);
		}//  4.节点X与Y为黑色,节点X的兄弟节点Y,只包含右孩子R且为红色,则删除节点X后,据P左旋,再将Y变为P的颜色,
		// 将P和R染黑。
		else if(y != NULL && l == NULL && r != NULL && rb_is_red(r) && rb_is_black(x) && rb_is_black(y)){
			p->left = NULL;
			delete x;
			leftRotate(root, p); // 根据p左旋
			y->color = p->color;
			rb_set_black(p);
			rb_set_black(r);
		}// 5.节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,再根据P进行左旋,再将Y变为P的颜色,
		 // P和R变黑
		else if(y != NULL && l != NULL && r != NULL && rb_is_red(l) && rb_is_red(r) && rb_is_black(x) && rb_is_black(y)){
			p->left = NULL;
			delete x;
			leftRotate(root, p); // 根据p左旋
			y->color = p->color;
			rb_set_black(p);
			rb_set_black(r);
		}// 6. 被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比黑色。删除节点X,在根据P进行左旋,
		 // 再将Y染黑,L染红
 		else if(y != NULL && rb_is_red(y) && l != NULL && r != NULL && rb_is_black(l) && rb_is_black(r) && rb_is_black(x)){
 			p->left = NULL;
			delete x;
			leftRotate(root, p); // 根据p左旋
			rb_set_black(y);
 			rb_set_red(l);
		}	
	}// 再判断删除的叶子节点为父节点的右孩子情况 
	else{
		y = p->left; // x的兄弟节点
		if(y != NULL){
			l = y->left;
			r = y->right; 	
		}	
		// 1. 删除节点为红色,不管是父节点的左孩子还是右孩子,则直接删除
		if(rb_is_red(x)){
			p->right = NULL;
			delete x;
		}// 2.删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色
		else if(y == NULL || (rb_is_black(x) && rb_is_black(y) && l == NULL && r == NULL)){
			p->right = NULL;
			delete x;
			rb_set_black(p);
			if(y != NULL){
				rb_set_red(y);
			}
		}// 3.节点X为父节点的右节点,节点X与Y为黑色,且节点X的兄弟节点Y只包含右孩子R且为红色,则删除节点X后,
		 // 需要先根据Y左旋,再据P右旋,将R变为P的颜色,再将P染黑
		else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r != NULL && l == NULL && rb_is_red(r)){
			p->right = NULL;
			delete x;
			leftRotate(root, y); // 根据y左旋
			rightRotate(root, p); // 根据p右旋
			r->color = p->color; // 将R变为P的颜色
			rb_set_black(p); // 将P染黑
		}// 4.节点X为父节点的右节点,节点X与Y为黑色,且节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,
		// 根据P右旋,将Y变为P的颜色,再将P和L染黑
		else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r == NULL && l != NULL && rb_is_red(l)){
			p->right = NULL;
			delete x;
			rightRotate(root, p); // 根据p右旋
			y->color = p->color;
			rb_set_black(p); // 将P染黑
			rb_set_black(l); // 将P染黑 
		}// 5.节点X为父节点的右节点,节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,
		 // 再根据P进行右旋,再将Y变为P的颜色,P和L变黑
		else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r != NULL && l != NULL && rb_is_red(l) && rb_is_red(r)){
			p->right = NULL;
			delete x;
			rightRotate(root, p); // 根据p右旋
			y->color = p->color;
			rb_set_black(p); // 将P染黑
			rb_set_black(l); // 将P染黑 
		}// 6.节点X为父节点的右孩子,被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比为黑色。
		 // 删除节点X,在根据P进行右旋,再将Y染黑,R染红
		else if(y != NULL && rb_is_black(x) && rb_is_red(y) && r != NULL && l != NULL && rb_is_black(l) && rb_is_black(r)){
			p->right = NULL;
			delete x;
			rightRotate(root, p); // 根据p右旋
			rb_set_black(y); // 将y染黑
			rb_set_red(r); // 将r染红 
		}
	} 
}
// 删除节点(key为节点键值)
template 
void RBTree::remove(T key){
	RBTNode* node;
	// 查找key对应的节点node,找到的话就删除该节点
	if((node = search(mRoot, key)) != NULL){
		removeFixUp(mRoot, node, NULL);
	} 
}

template
void RBTree::destroy(RBTNode* &tree){
	if(tree == NULL){
		return;
	}
	destroy(tree->left);
	destroy(tree->right);
	delete tree;
	tree = NULL;
}
template
void RBTree::destroy(){
	destroy(mRoot);
}

template
void RBTree::print(RBTNode* &tree, T key, int direction){
	if(tree != NULL){
		if(direction == 0){ // tree是根节点 
			cout << setw(2) << tree->key << "(B) is root" << endl;
		}else{
			cout << setw(2) << tree->key << (rb_is_red(tree) ? "(R)":"(B)") << " is " << setw(2) << key
			<< " 's " << setw(12) << (direction == 1 ? "right child":"left child") << endl;
		}
		print(tree->left, tree->key, -1);
		print(tree->right, tree->key, 1);
	}	
}
template
void RBTree::print(){
	if(mRoot != NULL){
		print(mRoot, mRoot->key, 0);
	}
}
int main(){
	cout << "hello1111" << endl; 
	int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
	int check_insert = 0; // “插入”动作的检测开关(0,关闭;1,打开)
	int check_remove = 0; // “删除”动作的检测开关(0,关闭;1,打开)
	int i;
	int len = (sizeof(a))/sizeof(a[0]); 
	RBTree* tree = new RBTree();
	cout << "====原始数据:";
	for(i = 0; i < len; i++){
		cout << a[i] << " ";
	}
	cout << endl;
	for(i = 0; i < len; i++){
		tree->insert(a[i]);
		// 设置check_insert=1,测试“添加函数”
		if(check_insert){
			cout << "==添加节点:" << a[i] << endl;
			cout << "==树的详细信息:" << endl;
			tree->print();
			cout << endl;
		} 
	}
	cout << "==前序遍历:";
	tree->preOrder();
	cout << endl;
	cout << "==中序遍历:";
	tree->inOrder();
	cout << endl;
	cout << "==后序遍历:";
	tree->postOrder();
	cout << endl; 
	cout << "==最小值:" << tree->minimum() << endl;
	cout << "==最大值:" << tree->maximum() << endl;
	cout << "==树的详细信息:" << endl;
	tree->print();
	cout << endl;
	// 设置check_remove = 1,测试“删除函数”
	check_remove = 1;
	if(check_remove){
		for(i = 0; i < len; i++){
			tree->remove(a[i]);
			cout << "==删除节点:" << a[i] << endl;
			cout << "==树的详细信息:" << endl;
			tree->print();
			cout << endl;
		}
	} 
	// 销毁红黑树
	tree->destroy(); 
	return 0;
}

在删除操作那儿,后续还要再改动下

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997461.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号