红黑树数据结构的C++实现模板(2)---结合抽象类

//"BTREE.h"
#pragma once
#ifndef RTREE
#define RTREE
#define RED 0
#define BLACK 1
#include<ctime>
#include<iostream>
/*.
* 定义红黑树的结点类
*/
template<class Type>
class RBTreeNode {
public:
	unsigned int color = -1;
	Type key;
	RBTreeNode <Type>* left;
	RBTreeNode <Type>* right;
	RBTreeNode <Type>* parent;
	RBTreeNode(Type key, int color, RBTreeNode<Type> * parent, RBTreeNode<Type> * left, RBTreeNode<Type>* right) :key(key),color(color),parent(parent),
		left(left),right(right)
	{};	
};
/*
*创建树类型
*
*/
template<class Type>
class RBTree {
 public:
	RBTreeNode<Type> * m_root;
	RBTree() {
		m_root = NULL;
	}
	~RBTree() {
		rbtree_destroy();
	}

	bool insert_rbtree(Type key);

	void delete_rbtree(Type key);

	void print_rbtree();

	RBTreeNode<Type>*  rb_parent(RBTreeNode<Type>*  node);

	bool isRedNode(RBTreeNode<Type>* node);

	bool isBlackNode(RBTreeNode<Type>* node);

	RBTreeNode<Type>*  search(RBTreeNode<Type>*x, Type key);

	bool rbtree_search(Type key);

	void preOrder(RBTreeNode<Type>* tree);

	void InOrder(RBTreeNode<Type>* tree);

	void preOrder_rbtree();

	void InOrder_rbtree();

private:
	void rbtree_print(RBTreeNode<Type>*tree, Type key, int direction);

	void destroyTree(RBTreeNode<Type>* tree);

	void  rbtree_destroy();

	void rbtree_insert(RBTreeNode<Type>*&root, RBTreeNode<Type>*newNode);

	void rebtree_insert_fixup(RBTreeNode<Type>*&root, RBTreeNode<Type>* node);

	void rbtree_left_rotate(RBTreeNode<Type>*&root, RBTreeNode <Type>* x);

	void rbtree_right_rotate(RBTreeNode<Type>*&root, RBTreeNode <Type>* x);

	void rbtree_delete(RBTreeNode<Type>*&root, RBTreeNode<Type>*newNode);

	void rebtree_delete_fixup(RBTreeNode<Type>*&root, RBTreeNode<Type>* node, RBTreeNode<Type>* parent);

};

#endif

#include"BTREE.h"
using namespace std;
//R - B Tree,全称是Red - Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
//红黑树的特性 :
//(1)每个节点或者是黑色,或者是红色。
//(2)根节点是黑色。
//(3)每个叶子节点(NIL)是黑色。[注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
//(4)如果一个节点是红色的,则它的子节点必须是黑色的。
//(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
//
//注意:
//(01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
//(02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
//定理:一棵含有n个节点的红黑树的高度至多为2log(n+1).

//处理红黑树的核心思想:将红色的节点移到根节点;然后,将根节点设为黑色。
//既然是“将红色的节点移到根节点”,那就是说要不断的将破坏红黑树特性的红色节点上移(即向根方向移动)。
//基本定义

//===============================关键函数区域============================================//

//左旋
/*
 * 对红黑树的节点(x)进行左旋转
 *
 * 左旋示意图(对节点x进行左旋):
 *      px                              px
 *     /                               /
 *    x                               y
 *   /  \      --(左旋)-->           / \                #
 *  lx   y                          x  ry
 *     /   \                       /  \
 *    ly   ry                     lx  ly
 *
 *
 */
template<class Type>
void RBTree<Type>::rbtree_left_rotate(RBTreeNode<Type>*&root, RBTreeNode<Type>*  x) {
	RBTreeNode <Type>* y = x->right;

	x->right = y->left;
	if (y->left != NULL)	y->left->parent = x;

	y->parent = x->parent;

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

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

}

//右旋
/*
 * 对红黑树的节点(y)进行右旋转
 *
 * 右旋示意图(对节点y进行左旋):
 *            py                               py
 *           /                                /
 *          y                                x
 *         /  \      --(右旋)-->            /  \                     #
 *        x   ry                           lx   y
 *       / \                                   / \                   #
 *      lx  rx                                rx  ry
 *
 */
template<class Type>
void RBTree<Type>::rbtree_right_rotate(RBTreeNode<Type>* &root, RBTreeNode<Type>* x) {
	RBTreeNode <Type>* y = x->left;
	x->left = y->right;

	if (y->right != NULL) y->right->parent = x;

	y->parent = x->parent;

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

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

template<class Type>
RBTreeNode<Type>* RBTree<Type>::rb_parent(RBTreeNode<Type>* node) {
	if (node && node->parent)
		return node->parent;
	else return NULL;
}

template<class Type>
bool RBTree<Type>::isRedNode(RBTreeNode<Type>* node) {
	return node->color == RED;
}

template<class Type>
bool  RBTree<Type>::isBlackNode(RBTreeNode<Type>* node){
	return node->color == BLACK;
}

template<class Type>
 RBTreeNode<Type>*  RBTree<Type> ::search(RBTreeNode<Type>*x, Type key)
{
	if (x == NULL || x->key == key)
		return x;

	if (key < x->key)
		return search(x->left, key);
	else
		return search(x->right, key);
}

template<class Type>
bool RBTree<Type> ::rbtree_search( Type key)
{
	if (m_root)
		return search(m_root, key) ? true : false;
	else
		cout << key << "不存在" << endl;
	return false;
}

//添加
//先将红黑树当作一颗二叉查找树,将节点插入;然后,将节点着色为红色;
//最后,通过"旋转和重新着色"等一系列操作来修正该树,使之重新成为一颗红黑树。
template<class Type>
void RBTree<Type>::rbtree_insert(RBTreeNode<Type>*&root, RBTreeNode<Type>*newNode) {
	RBTreeNode<Type>*y = NULL;
	RBTreeNode<Type>*x = root;
	//1.当作是一棵二叉查找树,将点加入二叉排序树中
	while (x != NULL) {
		y = x;
		if (newNode->key < x->key) { x = x->left; }
		else x = x->right;
	}
	newNode->parent = y;
	if (y != NULL) {
		if (newNode->key < y->key)
			y->left = newNode;
		else
			y->right = newNode;
	}
	else {//y是空结点,把newNode作为根节点
		root = newNode;
	}
	//2.设置位红色
	newNode->color = RED;
	//3.修正为一棵二叉排序树
	rebtree_insert_fixup(root,newNode);
}
//4.1修正insert

//根据被插入节点的父节点的情况,可以将"当节点z被着色为红色节点,并插入二叉树"划分为三种情况来处理。
//① 情况说明:被插入的节点是根节点。
//处理方法:直接把此节点涂为黑色。
//② 情况说明:被插入的节点的父节点是黑色。
//处理方法:什么也不需要做。节点被插入后,仍然是红黑树。
//③ 情况说明:被插入的节点的父节点是红色,且父节点是爷结点的左孩子
//
		//Case 1	当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。
		//(01) 将“父节点”设为黑色。
		//(02) 将“叔叔节点”设为黑色。
		//(03) 将“祖父节点”设为“红色”。
		//(04) 将“祖父节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作。
//		
		//Case 2	当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子
		//(01) 将“父节点”作为“新的当前节点”。
		//(02) 以“新的当前节点”为支点进行左旋。
//		
		//Case 3	当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子
		//(01) 将“父节点”设为“黑色”。
		//(02) 将“祖父节点”设为“红色”。
		//(03) 以“祖父节点”为支点进行右旋。
template<class Type>
void RBTree<Type>::rebtree_insert_fixup(RBTreeNode<Type>*&root, RBTreeNode<Type>* node) {
	RBTreeNode<Type> *parent, *grandparent;
	//若父结点存在且父结点是红色
	while ((parent = node->parent) && isRedNode(parent)) {
		grandparent = parent->parent;

		if (parent == grandparent->left) {
			//Case1:uncle存在且他的颜色是红色的

			RBTreeNode<Type> *uncle = grandparent->right;

			if (uncle&&isRedNode(uncle)) {
				//情况1:父亲和叔叔都是红色
				uncle->color = parent->color = BLACK;
				grandparent->color = RED;
				node = grandparent;
				continue;
			}
			else {	//等效于else if ((uncle && !isRedNode(uncle))||!uncle) {
				if (parent->right == node) {
					//Case2:父亲是红色,叔叔是黑色,node是右孩子==》父亲为左旋中心,把孩子变成和父亲同线,和Case3一样
					//需要转为直线操作
					rbtree_left_rotate(root, parent);
					RBTreeNode<Type> * temp = parent;
					parent = node;
					node = temp;
				}
				else {//Case 3:当前为左孩子,直线操作
					//不用转为直线操作
				}
				parent->color = BLACK;
				grandparent->color = RED;
				rbtree_right_rotate(root, grandparent);
			}
		}


		else {
			RBTreeNode<Type> *uncle = grandparent->left;
			if (uncle && isRedNode(uncle)) {
				//Case1 1:both red
				uncle->color = parent->color = BLACK;
				grandparent->color = RED;
				node = grandparent;
				continue;
			}
			else {
				if (parent->left == node) {//Case 2:需要右旋
					rbtree_right_rotate(root, parent);
					RBTreeNode<Type> * temp = parent;
					parent = node;
					node = temp;
				}
				//Case 3:需要左旋
				parent->color = BLACK;
				grandparent->color = RED;
				rbtree_left_rotate(root, grandparent);
			}

		}//else
	}//while
	// 将根节点设为黑色
	root->color = BLACK;
}

/*
 * 新建结点(节点键值为key),并将其插入到红黑树中
 *
 * 参数说明:
 *     root 红黑树的根
 *     key 插入结点的键值
 * 返回值:
 *     0,插入成功
 *     -1,插入失败
 */
template<class Type>
bool RBTree<Type> ::insert_rbtree(Type key)
{
	RBTreeNode<Type>* node =NULL;    // 新建结点
	// 不允许插入相同键值的节点。
	// (若想允许插入相同键值的节点,注释掉下面两句话即可!)
	if (search(m_root, key))
		return false;

	// 如果新建结点失败,则返回。
	if (  ( node= new RBTreeNode<Type>(key, BLACK, NULL, NULL, NULL))== NULL)
		return false;
	rbtree_insert( m_root,node);
	cout << endl;
	print_rbtree();
	cout << endl;
	return true;
}

//
/* .打印"红黑树"
 *
 * tree       -- 红黑树的节点
 * key        -- 节点的键值
 * direction  --  0,表示该节点是根节点;
 *               -1,表示该节点是它的父结点的左孩子;
 *                1,表示该节点是它的父结点的右孩子。
 */
template<class Type>
void RBTree<Type> ::rbtree_print(RBTreeNode<Type>*tree, Type key, int direction)
{
	if (tree != NULL)
	{
		if (direction == 0)    // tree是根节点
			printf("%2d(B) is root\n", tree->key);
		else                // tree是分支节点
			printf("%2d(%s) is %2d's %6s child\n", tree->key, isRedNode(tree) ? "R" : "B", key, direction == 1 ? "right" : "left");
		rbtree_print(tree->left, tree->key, -1);
		rbtree_print(tree->right, tree->key, 1);
	}
}

template<class Type>
void RBTree<Type> ::print_rbtree()
{
	if (m_root != NULL )
		rbtree_print(m_root, m_root->key, 0);
	else
		cout << "为空树" << endl;
}

template<class Type>
void RBTree<Type>::destroyTree(RBTreeNode<Type>* tree) {
	if (!tree) return;
	if (tree->left)destroyTree(tree->left);
	if (tree->right)destroyTree(tree->right);
	delete tree;
}

template<class Type>
void RBTree<Type>::rbtree_destroy() {
	if (m_root != NULL) {
		destroyTree(m_root);
		cout << "delete finished." << endl;
	}
	delete m_root;
}

template<class Type>
void RBTree<Type>::rbtree_delete( RBTreeNode<Type>*&root, RBTreeNode<Type>*node) {
	RBTreeNode<Type>* child = NULL;
	RBTreeNode<Type>* parent;
	int color = -1;
	//左右孩子全有时
	if ((node->right != NULL) && (node->left != NULL)) {
		RBTreeNode<Type>* rChild;
		RBTreeNode<Type>* replace = node->right;
		while (replace->left != NULL) {
			replace = replace->left;
		}//replace 是node的中序遍历后继点

		//==(1)==动node的父母=====//
		if (node->parent != NULL) {
			if (node->parent->left == node) {
				node->parent->left = replace;
			}
			else
				node->parent->right = replace;
		}
		else root = replace;//情况①   "node节点"是根节点,更新根节点。


		int color = replace->color;
		rChild = replace->right;   // child是"取代节点"的右孩子,也是需要"调整的节点"。
	   // "取代节点"肯定不存在左孩子!因为它是一个后继节点。
		parent = replace->parent;//先是replace的父母,后来是replace的孩子的父母


		//=(2)==动replace的原、现右分支关系====//
	   //分2种情况,1:replace是node的右结点;2:node和replace中还有很多结点
		if (parent == node) {
			parent = replace;//不用改动右孩子关系
		}
		else {
			//先连接replace的父子
			if (rChild) {
				rChild->parent = parent;
			}
			parent->left = rChild;

			//再连接replace的新右孩子
			replace->right = node->right;
			node->right->parent = replace;
		}


		//==(3)===动replace左分支现关系===//
		replace->color = node->color;
		replace->parent = node->parent;
		replace->left = node->left;
		node->left->parent = replace;

		if (color == BLACK) {//双黑情况
			rebtree_delete_fixup(root, rChild, parent);
		}
		delete node;
		return;
	}

	color = node->color;
	parent = node->parent;

	if (node->right != NULL)
		child = node->right;
	else
		child = node->left;


	if (child) {
		child->parent = parent;
	}

	if (parent) {//node不是root
		if (parent->left == node) {
			parent->left = child;
		}
		else {
			parent->right = child;
		}
	}
	else {//node是root
		root = child;
	}

	if (color == BLACK) {
		rebtree_delete_fixup(root, child, parent);
	}
	delete node;
}

//5.1 修正delete
template<class Type>
void RBTree<Type>::rebtree_delete_fixup(RBTreeNode<Type>*&root, RBTreeNode<Type>*node, RBTreeNode<Type>* parent) {
	//思想:将x所包含的额外的黑色不断沿树上移(向根方向移动)
	//node不存在或node是黑色且非根节点
	RBTreeNode<Type>*  broNode;
	while ((!node || isBlackNode(node)) && node != root) {
		if (node == parent->left) {
			broNode = parent->right;
			//Case 1:x是"黑+黑"节点,x的兄弟节点是红色
			if (isRedNode(broNode)) {
				broNode->color = BLACK;
				parent->color = RED;
				rbtree_left_rotate(root, parent);
				broNode = parent->right;
			}//目的是将“Case 1”转换为“Case 2”、“Case 3”或“Case 4”,从而进行进一步的处理。

			//Case 2	x是“黑 + 黑”节点,x的兄弟节点是黑色,x的兄弟节点的两个孩子都是黑色(NULL也是黑色)
			if ((!broNode->right || isBlackNode(broNode->right)) &&
				(!broNode->left || isBlackNode(broNode->left))) {
				broNode->color = RED;
				node = parent;
				parent = node->parent;
			}//目的:所有经过x的兄弟节点的分支中黑色节点的个数减1
			else {
				if (!broNode->right || isBlackNode(broNode->right)) {
					//Case 3	x是“黑 + 黑”节点,x的兄弟节点是黑色;x的兄弟节点的左孩子是红色,右孩子是黑色的。
					broNode->left->color = BLACK;
					broNode->color = RED;
					rbtree_right_rotate(root, broNode);
					broNode = parent->right;
				}//  使得parent-broNode-(broNode->right)   :红-黑-红直线
				 // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
				broNode->color = node->parent->color;
				parent->color = BLACK;
				broNode->right->color = BLACK;

				rbtree_left_rotate(root, parent);
				node = root;
				break;
			}
		}
		else {
			broNode = parent->left;
			//Case 1:x是"黑+黑"节点,x的兄弟节点是红色
			if (isRedNode(broNode)) {
				broNode->color = BLACK;
				parent->color = RED;
				rbtree_right_rotate(root, parent);
				broNode = parent->left;
			}//目的是将“Case 1”转换为“Case 2”、“Case 3”或“Case 4”,从而进行进一步的处理。

			//Case 2	x是“黑 + 黑”节点,x的兄弟节点是黑色,x的兄弟节点的两个孩子都是黑色(NULL也是黑色)
			if ((!broNode->right || isBlackNode(broNode->right)) &&
				(!broNode->left || isBlackNode(broNode->left))) {
				broNode->color = RED;
				node = parent;
				parent = node->parent;
			}//目的:所有经过x的兄弟节点的分支中黑色节点的个数减1

			else {
				if (!broNode->left || isBlackNode(broNode->left)) {
					//Case 3	x是“黑 + 黑”节点,x的兄弟节点是黑色;x的兄弟节点的右孩子是红色,左孩子是黑色的。
					broNode->right->color = BLACK;
					broNode->color = RED;
					rbtree_left_rotate(root, broNode);
					broNode = parent->left;
				}//  使得parent-broNode-(broNode->right)   :红-黑-红直线
				 // Case 4: x的兄弟w是黑色的;并且w的左孩子是红色的,右孩子任意颜色。

				broNode->color = node->parent->color;
				parent->color = BLACK;
				broNode->left->color = BLACK;

				rbtree_right_rotate(root, parent);
				node = root;
				break;
			}
		}
	}
	//node根节点
	if (node) node->color = BLACK;
}

/*
 * 删除键值为key的结点
 *
 * 参数说明:
 *     tree 红黑树的根结点
 *     key 键值
 */
template<class Type>
void RBTree<Type>::delete_rbtree( Type key)
{
	RBTreeNode<Type>* z;
	if ((z = search(m_root, key)) != NULL)
		rbtree_delete(m_root, z);
	else cout << key << "不存在" << endl;
}

//7.前序遍历
template<class Type>
void RBTree<Type>::preOrder(RBTreeNode<Type>* tree) {
	if (tree) {
		cout << tree->key << " ";// << "--" << (tree->color == 0 ? "red" : "black") << endl;
		preOrder(tree->left);
		preOrder(tree->right);
	}
}
template<class Type>
void RBTree<Type>::preOrder_rbtree() {
	if (m_root) {
		preOrder(m_root);
		cout << endl;
	}
}
//8.中序
template<class Type>
void RBTree<Type>::InOrder(RBTreeNode<Type>* tree) {
	if (tree) {
		InOrder(tree->left);
		cout << tree->key << " ";
		InOrder(tree->right);
	}
}
template<class Type>
 void RBTree<Type>::InOrder_rbtree() {
	if (m_root) {
		InOrder(m_root);
		cout << endl;
	}
}


int main() {
	int a[] = { 10, 40, 30, 60, 90, 70, 20, 50, 80 };
	RBTree <int> * rbtree=new RBTree<int>();
	for(int i=0;i<9;i++)
		rbtree->insert_rbtree(a[i]);
	rbtree->print_rbtree();
	rbtree->preOrder_rbtree();
	rbtree->InOrder_rbtree();
	cout << "Input an number to be deleted:" << endl;
	int key=-1;
	cin >> key;
	rbtree->delete_rbtree( key);
	rbtree->print_rbtree();
	cout << "Input an number to be added:" << endl;
	cin >> key;
	rbtree->insert_rbtree(key);
	rbtree->print_rbtree();
}

发布了156 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44001521/article/details/104399813