红黑树类算法实现

继续参考Wiki(http://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91),资料如下:

性质

红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。


简单实现代码如下:

/*
	红黑树目标实现
	红黑树的平衡操作主要是参考平衡根的兄弟或者叔父节点的颜色来判断的,主要是性质黑色节点数一样的平衡。
	Author:BetaBin
	Date:2012.04.30
*/

#include <iostream>
#include <cstdio>

using namespace std;

//节点颜色值
#define BLACK 0
#define RED 1


//红黑树节点结构
template<class ValueType>
struct RbNode 
{
	ValueType data;
	int color;
	RbNode<ValueType> *left;
	RbNode<ValueType> *right;
	RbNode<ValueType> *parent;

	//一般用于NIL节点创建,颜色默认为黑色
	RbNode()
	{
		color = BLACK;
	}

	//一般用于新节点创建,颜色默认为红色
	RbNode(ValueType value)
	{
		color = RED;
		data = value;
	}
	
};


//红黑树模板类
//实现简单的中序遍历输出、插入、删除操作
//辅助的插入平衡、删除平衡、左旋、右旋
template<class ValueType>
class RbTree
{
public:
	RbTree();
	~RbTree();
	void InfixOutput(RbNode<ValueType>* node);	//中序遍历输出结果,用作测试
	void InsertData(ValueType value);			//插入新数据,重复会被忽视,既是不插入
	void EraseData(ValueType value);			//删除数据

	RbNode<ValueType> *root;	//树根节点指针
	RbNode<ValueType> *NIL;		//树NIL哨兵节点指针

private:
	RbNode<ValueType>* FindValue(ValueType value);	//寻找对应值的节点
	RbNode<ValueType>* InfixSuccessor(RbNode<ValueType>* node);//寻找中序遍历后继,无后继则返回NIL

	void LeftRotate(RbNode<ValueType>* node);		//左旋
	void RightRotate(RbNode<ValueType>* node);		//右旋
	void DestroyTree(RbNode<ValueType>* root);		//销毁以root为根的树

	void InsertBalance(RbNode<ValueType>* node);	//插入平衡操作
	void EraseBalance(RbNode<ValueType>* node);		//删除平衡操作
};

template<class ValueType>
RbTree<ValueType>::RbTree()
{
	//创建哨兵
	NIL = new RbNode<ValueType>();
	root = NIL;
}

template<class ValueType>
RbTree<ValueType>::~RbTree()
{
	//销毁树节点内存和哨兵
	if (NIL != root)
	{
		DestroyTree(root);
	}

	delete NIL;
}

template<class ValueType>
void RbTree<ValueType>::DestroyTree(RbNode<ValueType>* treeRoot)
{
	if (NIL != treeRoot->left)
	{
		DestroyTree(treeRoot->left);
	}

	if (NIL != treeRoot->right)
	{
		DestroyTree(treeRoot->right);
	}

	delete treeRoot;
}

//寻找中序遍历后继
template<class ValueType>
RbNode<ValueType>* RbTree<ValueType>::InfixSuccessor(RbNode<ValueType>* node)
{
	if (NIL == node->right)
	{
		//后继在祖宗处
		RbNode<ValueType>* parent = node->parent;
		while (parent != NIL && node == parent->right)
		{
			parent = node;
			node = node->parent;
		}
	}
	else
	{
		//节点有右子树情况下,递归至最左节点
		node = node->right;
		while (NIL != node->left)
		{
			node = node->left;
		}
	}

	return node;
}

//中序遍历输出,用作测试
template<class ValueType>
void RbTree<ValueType>::InfixOutput(RbNode<ValueType>* node)
{
	if (NIL != node)
	{
		InfixOutput(node->left);
		cout << node->data << endl;
		InfixOutput(node->right);
	}
}

//左旋:\旋转变为/理解
template<class ValueType>
void RbTree<ValueType>::LeftRotate(RbNode<ValueType>* node)
{
	//先改变x和y子树转移
	RbNode<ValueType>* temp = node->right;
	node->right = temp->left;
	if (NIL != temp->left)
	{
		temp->left->parent = node;
	}

	//完成x和y父亲转移
	temp->parent = node->parent;
	if (NIL == node->parent)
	{
		root = temp;
	}
	else if (node == node->parent->left)
	{
		node->parent->left = temp;
	} 
	else
	{
		node->parent->right = temp;
	}

	//完成x和y两者之间关系转移
	temp->left = node;
	node->parent = temp;
}

//右旋:/旋转变为\理解
template<class ValueType>
void RbTree<ValueType>::RightRotate(RbNode<ValueType>* node)
{
	//先完成x和y子树转移
	RbNode<ValueType>* temp = node->left;
	node->left = temp->right;
	if (NIL != temp->right)
	{
		node->left->parent = node;
	}

	//完成x和y父亲转移
	temp->parent = node->parent;
	if (NIL == node->parent)
	{
		root = temp;
	}
	else if (node->parent->left == node)//不小心删掉一个等号,愣是找了N久错误,勿先入为主
	{
		node->parent->left = temp;
	} 
	else
	{
		node->parent->right = temp;
	}

	//完成x和y之间转移
	temp->right = node;
	node->parent = temp;
}

//寻找值
template<class ValueType>
RbNode<ValueType>* RbTree<ValueType>::FindValue(ValueType value)
{
	RbNode<ValueType>* scanner = root;
	while (NIL != scanner)
	{
		if (value == scanner->data)
		{
			break;
		} 
		else if (value < scanner->data)
		{
			scanner = scanner->left;
		} 
		else
		{
			scanner = scanner->right;
		}
	}

	return scanner;
}

//插入数据
template<class ValueType>
void RbTree<ValueType>::InsertData(ValueType value)
{
	//已经存在,不需要重复插入
	if (NIL != FindValue(value))
	{
		return ;
	}	

	RbNode<ValueType> *current = root;
	RbNode<ValueType> *pre = NIL;
	RbNode<ValueType> *newNode = new RbNode<ValueType>(value);

	//找到插入位置:pre子树
	while (current != NIL)
	{
		pre = current;
		if (current->data > value)
		{
			current = current->left;
		}
		else
		{
			current = current->right;
		}
	}

	//新节点关系链更新
	newNode->parent = pre;

	if (NIL == pre)
	{
		root = newNode;
	}
	else if (value < pre->data)
	{
		pre->left = newNode;
	}
	else
	{
		pre->right = newNode;
	}

	newNode->left = NIL;
	newNode->right = NIL;

	//插入平衡操作
	InsertBalance(newNode);
}

//共六种情况,按照对称有三种讨论
//1、node的叔叔y是红色的
//2、node的叔叔y是黑色的,而且node是右孩子
//3、node的叔叔y是黑色的,而且node是左孩子
template<class ValueType>
void RbTree<ValueType>::InsertBalance(RbNode<ValueType>* node)
{
	while (RED == node->parent->color)
	{
		RbNode<ValueType>* uncle;
		//父节点为左节点时处理,另一种情况为父节点为右节点
		if (node->parent == node->parent->parent->left)
		{
			uncle = node->parent->parent->right;
			//叔为红节点时,直接颜色转换即可
			if (RED == uncle->color)
			{
				node->parent->color = BLACK;
				uncle->color = BLACK;
				node->parent->parent->color = RED;
			}
			else
			{
				//否则先判断是否需要左旋
				//将位置转为/形状
				if (node == node->parent->right)
				{
					node = node->parent;
					LeftRotate(node);
				}
				//颜色重设后直接右旋
				node->parent->color = BLACK;
				node->parent->parent->color = RED;
				RightRotate(node->parent->parent);
			}
		}
		else
		{
			//同上三种情况分析,对称处理
			uncle = node->parent->parent->left;
			if (RED == uncle->color)
			{
				node->parent->color = BLACK;
				uncle->color = BLACK;
				node->parent->parent->color = RED;
			}
			else
			{
				if (node == node->parent->left)
				{
					node = node->parent;
					RightRotate(node);
				}
				node->parent->color = BLACK;
				node->parent->parent->color = RED;
				LeftRotate(node->parent->parent);
			}
		}
	}

	//根节点颜色刷新
	root->color = BLACK;
}

//先确定需要删除的节点,可以是自身(不同时有两个子节点的情况下),也可以是一个替换节点。
//找到需要删除节点的一个非空子节点(需要删除的节点最多只有一个非空子节点)或空子节点
//断开需要删除节点指针,连接其子节点和父节点
//再判断是否删除还是替换内容
template<class ValueType>
void RbTree<ValueType>::EraseData(ValueType value)
{
	RbNode<ValueType>* nodetodelete;
	RbNode<ValueType>* nodetodeletechild;
	RbNode<ValueType>* target = FindValue(value);

	//要删除的key不存在
	if (NIL == target)
	{
		return ;
	}

	//找到要真正要删除的节点
	if (NIL == target->left || NIL == target->right)
	{
		nodetodelete = target;
	}
	else
	{
		nodetodelete = InfixSuccessor(target);
	}

	//找到nodetodelete的需要连接子节点
	if (NIL == nodetodelete->left)
	{
		nodetodeletechild = nodetodelete->right;
	} 
	else
	{
		nodetodeletechild = nodetodelete->left;
	}

	//断开删除节点,连接其父节点与子节点
	nodetodeletechild->parent = nodetodelete->parent;
	if (NIL == nodetodelete->parent)
	{
		root = nodetodeletechild;
	}
	else if (nodetodelete == nodetodelete->parent->left)
	{
		nodetodelete->parent->left = nodetodeletechild;
	}
	else
	{
		nodetodelete->parent->right = nodetodeletechild;
	}

	//需要内容覆盖的情况
	if (nodetodelete != target)
	{
		target->data = nodetodelete->data;
	}

	//删除节点为黑色的则需要平衡操作
	if (BLACK == nodetodelete->color)
	{
		EraseBalance(nodetodeletechild);
	}

	delete nodetodelete;
}

//共八种情况,对称处理四种情况
//1、node的兄弟是红色的
//2、node的兄弟是黑色的,而且兄弟的两个孩子都是黑色的
//3、node的兄弟是黑色的,而且兄弟的左孩子是红色的,右孩子是黑色的
//4、node的兄弟是黑色的,而且兄弟的右孩子是红色的
template<class ValueType>
void RbTree<ValueType>::EraseBalance(RbNode<ValueType>* node)
{
	RbNode<ValueType>* brother;
	while (node != root && BLACK == node->color)
	{
		if (node == node->parent->left)
		{
			//兄弟节点变量赋值
			brother = node->parent->right;

			//Case1
			if (RED == brother->color)
			{
				brother->color = BLACK;
				node->parent->color = RED;
				LeftRotate(node->parent);
				brother = node->parent->right;
			}

			//Case2
			if (BLACK == brother->left->color && BLACK == brother->right->color)
			{
				brother->color = RED;
				node = node->parent;
			}//Case3
			else if (BLACK == brother->right->color)
			{
				brother->left->color = BLACK;
				brother->color = RED;
				RightRotate(brother);
				brother = node->parent->right;
			}//Case4
			else
			{
				brother->color = node->parent->color;
				node->parent->color = BLACK;
				brother->right->color = BLACK;
				LeftRotate(node->parent);
				node = root;
			}
		}
		else
		{
			//兄弟节点变量赋值
			brother = node->parent->left;

			//Case1
			if (RED == brother->color)
			{
				brother->color = BLACK;
				node->parent->color = RED;
				RightRotate(node->parent);
				brother = node->parent->left;
			}

			//Case2
			if (BLACK == brother->left->color && BLACK == brother->right->color)
			{
				brother->color = RED;
				node = node->parent;
			}//Case3
			else if (BLACK == brother->left->color)
			{
				brother->right->color = BLACK;
				brother->color = RED;
				LeftRotate(brother);
				brother = node->parent->left;
			}//Case4
			else
			{
				brother->color = node->parent->color;
				node->parent->color = BLACK;
				brother->left->color = BLACK;
				RightRotate(node->parent);
				node = root;
			}
		}
	}

	node->color = BLACK;
}

int main()
{
	RbTree<int> test;
	int selection;
	int inputdata;

	do 
	{
		cout << "Input selection(0:insert;1:erase;2:quit;3:InfixPrint)";
		cin >> selection;

		switch (selection)
		{
		case 0:
			cout << "Please input the data to insert:";
			cin >> inputdata;
			test.InsertData(inputdata);
			break;
		case 1:
			cout << "Please input the data to delete:";
			cin >> inputdata;
			test.EraseData(inputdata);
			break;
		case 2:
			break;
		case 3:
			test.InfixOutput(test.root);
		default:;
		}
	} while (2 != selection);

	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值