红黑树的读书笔记

原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。

由于各种原因,可能存在诸多不足,欢迎斧正!

       

       最近开始了自己高级数据结构之旅,在这次旅行中,我将持续把一些高级的数据结构从理论到编码都过一遍,同时通过博客形式分享出来,希望大家指出不足之处!

       二叉排序树是一种动态排序的数据结构,支持插入、删除、查找等操作,且平均时间复杂度为O(log(N)),但是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N)。此时,平衡二叉树的产生了。平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树很难,于是人们使用AVL、红黑树、Treap、伸展树等来替代平衡二叉树,这些数据结构可以很好地改善最坏情况。但实现起来并不是很容易的事。

      红黑树是一种近似平衡的数据结构,插入、删除、查找等的平均时间复杂度均为O(N),它是复杂的,但它的操作有着良好的最坏情况效率。 红黑树放松了对平衡的限制。可以不再是严格意义上的平衡二叉树。

 平衡二叉树满足以下性质:

    (1)、红黑树节点要么是红节点、要么是黑节点;
    (2)、根节点为黑节点;
   (3)、叶节点(空节点)为黑节点;
   (4)、每个红节点的两个子节点是黑节点;
    (5)、对于每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点。

     关于插入、删除等平衡调整过程,请看大牛http://blog.csdn.net/v_july_v/article/details/6543438的博客,我的主要思想学习自其中,在此致谢!

     下面贴段代码:RedBlackNode.h

#include<iostream>
using namespace std;
const bool RED=true;
const bool BLACK=false;

struct RedBlackNode
{
	RedBlackNode *parent;
	RedBlackNode *leftChild;
	RedBlackNode *rightChild;
	int key;
	bool color;
	RedBlackNode(int tempKey)
	{
		key=tempKey;
		parent=NULL;
		leftChild=NULL;
		rightChild=NULL;
	    color=RED;
	}
};


  以下是算法主文件

    
#include<iostream>
#include"RedBlackNode.h"
using namespace std;

class RedBlackTree
{
private:
	RedBlackNode *Root;
public:
	RedBlackTree();
	RedBlackNode *GetRoot();
	RedBlackNode *FindRB(int );
	void UpdataRBNode(int,int);
	void InsertRBNode(int);
	void InsertFixUp(RedBlackNode *);
	void LeftRotate(RedBlackNode *);
	void RightRotate(RedBlackNode *);
	void DeleteFixUp(RedBlackNode *);
	bool DeleteRBNode(int);
	void DeleteNoOrOneChildNode(RedBlackNode *,RedBlackNode *);
	void PreOrderPrint(RedBlackNode *);
	void InOrderPrint(RedBlackNode *);
	void SufOrderPrint(RedBlackNode *);
	void RotatePrint(RedBlackNode *,int);
};

RedBlackTree::RedBlackTree()
{
	Root=NULL;
}

/**********************************************************
*参数:无
*返回值:空
*功能:返回红黑树根节点
************************************************************/
RedBlackNode *RedBlackTree::GetRoot()
{
	return this->Root;
}

/**********************************************************
*参数:待插入值
*返回值:空
*功能:插入新结点
************************************************************/
void RedBlackTree::InsertRBNode(int tempKey)
{
	RedBlackNode *pre=NULL,*cur=this->Root;
	while(cur!=NULL)
	{
		pre=cur;
		if(cur->key>tempKey)//tempKey插到左子树
			cur=cur->leftChild;
		else cur=cur->rightChild;//插到左子树
	}
	RedBlackNode *tempNode=new RedBlackNode(tempKey);
	tempNode->parent=pre;
	if(pre==NULL)//若插入的为根节点
	{
		this->Root=tempNode;
	}
	else if(pre->key>tempNode->key)
		pre->leftChild=tempNode;
	else pre->rightChild=tempNode;
	
	InsertFixUp(tempNode);//保持红黑树性质
}

/**********************************************************
*参数:待查找值
*返回值:若找到则返回所在节点,否则返回NULL
*功能:插入新结点
************************************************************/
RedBlackNode *RedBlackTree::FindRB(int tempKey)
{
	RedBlackNode *cur=this->Root;
	while(cur!=NULL)
	{
		if(cur->key==tempKey)
			break;
		else if(cur->key>tempKey)
			cur=cur->leftChild;
		else cur=cur->rightChild;
	}
	return cur;
}

/**********************************************************
*参数:待修改数值oldKey,修改后的数值newKey
*返回值:空
*功能:更新节点元素
************************************************************/
void RedBlackTree::UpdataRBNode(int oldKey,int newKey)
{
	DeleteRBNode(oldKey);
	InsertRBNode(newKey);
}

/**********************************************************
*参数:当前节点
*返回值:空
*功能:左旋
************************************************************/
void RedBlackTree::LeftRotate(RedBlackNode *tempNode)
{
	RedBlackNode *rChildNode=tempNode->rightChild;
	if(rChildNode->leftChild!=NULL)//左子树的右子树不为空
		rChildNode->leftChild->parent=tempNode;
	rChildNode->parent=tempNode->parent;
	if(NULL==tempNode->parent)//当前节点为根节点
		this->Root=rChildNode;
	else if(tempNode==tempNode->parent->leftChild)
		tempNode->parent->leftChild=rChildNode;
	else tempNode->parent->rightChild=rChildNode;
	tempNode->parent=rChildNode;
	tempNode->rightChild=rChildNode->leftChild;
	rChildNode->leftChild=tempNode;
}

/**********************************************************
*参数:当前节点
*返回值:空
*功能:右旋
************************************************************/
void RedBlackTree::RightRotate(RedBlackNode *tempNode)
{
	RedBlackNode *lChildNode=tempNode->leftChild;
	if(lChildNode->rightChild!=NULL)//左子树的右子树不为空
		lChildNode->rightChild->parent=tempNode;
	lChildNode->parent=tempNode->parent;
	if(NULL==tempNode->parent)//当前节点为根节点
		this->Root=lChildNode;
	else if(tempNode==tempNode->parent->leftChild)
		tempNode->parent->leftChild=lChildNode;
	else tempNode->parent->rightChild=lChildNode;
	tempNode->parent=lChildNode;
	tempNode->leftChild=lChildNode->rightChild;
	lChildNode->rightChild=tempNode;
}

/**********************************************************
*参数:当前插入节点
*返回值:空
*功能:在插入节点后加以调整保持红黑树性质
************************************************************/
void RedBlackTree::InsertFixUp(RedBlackNode *tempNode)
{
	RedBlackNode *parTempNode=tempNode->parent,*ancleTempNode;
	while(parTempNode!=NULL&&RED==parTempNode->color)//父节点不为空且为红色
	{
		if(parTempNode->parent!=NULL)
		{
			if(parTempNode->parent->leftChild==parTempNode)
			{
				ancleTempNode=parTempNode->parent->rightChild;
				if(ancleTempNode!=NULL&&RED==ancleTempNode->color)//叔叔节点为红色
				{
					parTempNode->color=BLACK;
					ancleTempNode->color=BLACK;
					parTempNode->parent->color=RED;
					tempNode=parTempNode->parent;//指向爷爷节点
					parTempNode=tempNode->parent;
				}
				else 
				{
					if(tempNode==parTempNode->rightChild)
					{
						LeftRotate(parTempNode);
						tempNode=tempNode->leftChild;
						parTempNode=tempNode->parent;
					}
					parTempNode->color=BLACK;
					parTempNode->parent->color=RED;
					RightRotate(parTempNode->parent);
					break;
				}
			}
			else 
			{
				ancleTempNode=parTempNode->parent->leftChild;
				if(ancleTempNode!=NULL&&RED==ancleTempNode->color)//叔叔节点为红色
				{
					parTempNode->color=BLACK;
					ancleTempNode->color=BLACK;
					parTempNode->parent->color=RED;
					tempNode=parTempNode->parent;//指向爷爷节点
					parTempNode=tempNode->parent;
				}
				else{
					if(tempNode==parTempNode->leftChild)
					{
						RightRotate(parTempNode);
						tempNode=tempNode->rightChild;
						parTempNode=tempNode->parent;
					}
					parTempNode->color=BLACK;
					parTempNode->parent->color=RED;
					LeftRotate(parTempNode->parent);
					break;
				}
			}
		}
		else break;
	}
	this->Root->color=BLACK;
}

/**********************************************************
*参数:pre待删除节点的父节点,cur待删除节点
*返回值:空
*功能:删除左右孩子有为空的情况
************************************************************/
void RedBlackTree::DeleteNoOrOneChildNode(RedBlackNode *pre,RedBlackNode *cur)
{
	if(NULL==cur->leftChild&&NULL==cur->rightChild)//左右孩子为空
	{
		if(NULL==pre)
			Root=NULL;
		else if(pre->leftChild==cur)
			pre->leftChild=NULL;
		else pre->rightChild=NULL;
		delete cur;
	}
	else if(cur->rightChild!=NULL)//若右子树不为空
	{
		if(NULL==pre)
		{
			Root=cur->rightChild;
			Root->parent=NULL;
		}
		else if(pre->leftChild==cur)
		{
			pre->leftChild=cur->rightChild;
			cur->rightChild->parent=pre;
		}
		else 
		{
			pre->rightChild=cur->rightChild;
			cur->rightChild->parent=pre;
		}
		delete cur;
	}
	else if(cur->leftChild!=NULL)//若左子树不为空
	{
		if(NULL==pre)
		{
			Root=cur->leftChild;
			Root->parent=NULL;
		}
		else if(pre->leftChild==cur)
		{
			pre->leftChild=cur->leftChild;
			cur->leftChild->parent=pre;
		}
		else
		{
			pre->rightChild=cur->leftChild;
			cur->leftChild->parent=pre;
		}
		delete cur;
	}
}

/**********************************************************
*参数:向上调平衡起点
*返回值:空
*功能:删除元素后调平衡
************************************************************/
void RedBlackTree::DeleteFixUp(RedBlackNode *tempNode)
{
	if(RED==tempNode->color)
		InsertFixUp(tempNode);
}

/**********************************************************
*参数:待删除节点元素值
*返回值:空
*功能:删除某元素值
************************************************************/
bool RedBlackTree::DeleteRBNode(int tempKey)
{
	RedBlackNode *pre=NULL,*cur=Root;
	while(cur!=NULL)//寻找待删除元素
	{
		if(cur->key==tempKey)
			break;
		else
		{
			pre=cur;
			if(cur->key>tempKey)
				cur=cur->leftChild;
			else cur=cur->rightChild;
		}
	}
	if(NULL==cur)return false;
	RedBlackNode *tempChild;
	bool tempColor;
	if(NULL==cur->leftChild||NULL==cur->rightChild)
	{
		if(NULL==cur->leftChild)//右孩子存在
			tempChild=cur->rightChild;
		else tempChild=cur->leftChild;
		tempColor=cur->color;
		DeleteNoOrOneChildNode(pre,cur);
		if(tempChild!=NULL&&BLACK==tempColor)
			DeleteFixUp(tempChild);
	}
	else //左右子树都不为空
	{
		RedBlackNode *rPre=cur,*rCur=cur->rightChild;//找到右子树最小元素
		while(rCur->leftChild!=NULL)
		{
			rPre=rCur;
			rCur=rCur->leftChild;
		}
		cur->key=rCur->key;
		tempChild=rCur->rightChild;//肯定无左孩子
		tempColor=rCur->color;
		DeleteNoOrOneChildNode(rPre,rCur);
		if(tempChild!=NULL&&BLACK==tempColor)
			DeleteFixUp(tempChild);
	}
	
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:前序遍历红黑树
************************************************************/
void RedBlackTree::PreOrderPrint(RedBlackNode *tempRoot)
{
	if(NULL==tempRoot)
		return ;
	cout<<"("<<tempRoot->key<<",";
	if(tempRoot->color)
		cout<<"红)  ";
	else cout<<"黑)  ";
	PreOrderPrint(tempRoot->leftChild);
	PreOrderPrint(tempRoot->rightChild);
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:中序遍历红黑树
************************************************************/
void RedBlackTree::InOrderPrint(RedBlackNode *tempRoot)
{
	if(NULL==tempRoot)
		return ;
	InOrderPrint(tempRoot->leftChild);
	cout<<"("<<tempRoot->key<<",";
	if(tempRoot->color)
		cout<<"红)  ";
	else cout<<"黑)  ";
	InOrderPrint(tempRoot->rightChild);
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:后序遍历红黑树
************************************************************/
void RedBlackTree::SufOrderPrint(RedBlackNode *tempRoot)
{
	if(NULL==tempRoot)
		return ;
	SufOrderPrint(tempRoot->leftChild);
	SufOrderPrint(tempRoot->rightChild);
	cout<<"("<<tempRoot->key<<",";
	if(tempRoot->color)
		cout<<"红)  ";
	else cout<<"黑)  ";
}

/**********************************************************
*参数:当前子树根节点,缩进列数
*返回值:空
*功能:翻转打印二叉查找树
************************************************************/
void RedBlackTree::RotatePrint(RedBlackNode *tempRoot,int tempColumn)
{
	if(NULL==tempRoot)
		return ;
	RotatePrint(tempRoot->leftChild,tempColumn+1);
	for(int i=0;i<tempColumn;i++)
		cout<<"    ";
	cout<<"("<<tempRoot->key<<",";
	if(tempRoot->color)
		cout<<"红)";
	else cout<<"黑)";
	cout<<endl;
	RotatePrint(tempRoot->rightChild,tempColumn+1);
}

int main()
{
	int val;
	while(true)
	{
		RedBlackTree myRedBlackTree;
		while(cin>>val)
		{
			if(val==0)break;
			myRedBlackTree.InsertRBNode(val);
		}
		cout<<endl<<"*****************************"<<endl;
		cout<<endl<<"=============前序============="<<endl;
		myRedBlackTree.PreOrderPrint(myRedBlackTree.GetRoot());
		cout<<endl<<"=============中序============="<<endl;
		myRedBlackTree.InOrderPrint(myRedBlackTree.GetRoot());
		cout<<endl<<"==============后序============="<<endl;
		myRedBlackTree.SufOrderPrint(myRedBlackTree.GetRoot());
		cout<<endl<<"==============对称+顺时针旋转============="<<endl;
		myRedBlackTree.RotatePrint(myRedBlackTree.GetRoot(),0);
		cout<<endl<<"============================="<<endl;
		cout<<"*****************************"<<endl;
		while(cin>>val)
		{
			if(!val)break;
			myRedBlackTree.DeleteRBNode(val);
			cout<<endl<<"*****************************"<<endl;
			cout<<endl<<"=============前序============="<<endl;
			myRedBlackTree.PreOrderPrint(myRedBlackTree.GetRoot());
			cout<<endl<<"=============中序============="<<endl;
			myRedBlackTree.InOrderPrint(myRedBlackTree.GetRoot());
			cout<<endl<<"==============后序============="<<endl;
			myRedBlackTree.SufOrderPrint(myRedBlackTree.GetRoot());
			cout<<endl<<"==============对称+顺时针旋转============="<<endl;
			myRedBlackTree.RotatePrint(myRedBlackTree.GetRoot(),0);
			cout<<endl<<"============================="<<endl;
			cout<<"*****************************"<<endl;
		}
	}
	system("pause");
	return 0;
}

         欢迎斧正!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值