算法导论-红黑树C++实现

原创 2012年11月10日 09:50:03

红黑树的定义:

一棵二叉查找树如果满足下面的红黑性质,则为一棵红黑树:

1)每个节点或是红的,或是黑的。

2)根节点是黑的。

3)每个叶节点(NIL)是黑节点。

4)如果一个节点是红的,则它的两个儿子都是黑的。

5)对每个节点,从该节点到其子孙节点的所有路径上包含相同节点数目的黑节点。


C++代码实现:

BRTreeNode.h

#ifndef BRTREENODE_H_INCLUDED
#define BRTREENODE_H_INCLUDED
#include<iostream>
using namespace std;
class BRTree;
class BRTreeNode
{
private:
	friend class BRTree;
	int key;
	bool color;
	BRTreeNode* left;
	BRTreeNode* right;
	BRTreeNode* parent;
public:
	BRTreeNode():key(-1),color(0),left(NULL),right(NULL),parent(NULL){}
	BRTreeNode(BRTreeNode* node):key(node->key),color(node->color),left(node->left),right(node->right),parent(node->parent)
	{}
	BRTreeNode(int num,bool flag):key(num),color(flag),left(NULL),right(NULL),parent(NULL){}
	~BRTreeNode()
	{

	}
	int Getkey()
	{
		return key;
	}
	bool Getcolor()
	{
		return this->color;
	}
	BRTreeNode* GetLeft()
	{
		return this->left;
	}
	BRTreeNode* Getright()
	{
		return this->right;
	}
	BRTreeNode* Getparent()
	{
		return this->parent;
	}
	void Inorder()
	{
		if(this!=NULL)
		{
			this->left->Inorder();
			cout<<this->key<<" ";
			this->right->Inorder();
		}
	}
	void Preorder()
	{
		if(this!=NULL)
		{
			cout<<this->key<<" ";
			this->left->Preorder();
			this->right->Preorder();
		}
	}
	void Postorder()
	{
		if(this!=NULL)
		{
			this->left->Postorder();
			this->right->Postorder();
			cout<<this->key<<" ";
		}
	}

	void MakeEmpty()
	{
		if(this!=NULL)
		{
			this->left->MakeEmpty();
			this->right->MakeEmpty();
			delete this;
		}
	}
	int GetHeight()
	{
		int L,R;
		if(this==NULL)
		{
			return 0;
		}
		L=this->left->GetHeight();
		R=this->right->GetHeight();
		return 1+(L>R? L:R);
	}
};


#endif // BRTREENODE_H_INCLUDED

BRTree.h

#ifndef BRTREE_H_INCLUDED
#define BRTREE_H_INCLUDED
#define maxSize 30
#define maxWidth 30
#include"BRTreeNode.h"
class BRTree
{
private:
	BRTreeNode* root;
	BRTreeNode* nil;
public:
	BRTree():nil(new BRTreeNode())
	{
		nil->color=0;
		nil->key=-1;
		nil->left=nil->right=nil->parent=NULL;
		root=nil;
	}
	~BRTree()
	{
		MakeEmpty(root);
		delete nil;
	}
	//清空以node为根节点的树
	void MakeEmpty(BRTreeNode*node)
	{
		if(node!=nil)
		{
			MakeEmpty(node->left);
			MakeEmpty(node->right);
			delete node;
		}
	}
	int Getkey(BRTreeNode* node)
	{
		return node->Getkey();
	}
	bool Getcolor(BRTreeNode* node)
	{
		return node->Getcolor();
	}
	BRTreeNode* Getroot()
	{
		return root;
	}
	BRTreeNode* GetParent(BRTreeNode*node)
	{
		return node->parent;
	}
	int GetHeight(BRTreeNode* node)
	{
		int L,R;
		if(node==nil)
			return 0;
		L=GetHeight(node->left);
		R=GetHeight(node->right);
		return 1+(L>R? L:R);
	}
    int GetBlackHeight(BRTreeNode* node)
	{
		int L,R;
		if(node==nil) return 0;
		L=GetHeight(node->left);
		R=GetHeight(node->right);
		if(node->Getcolor()) return(L>R? L:R);
		else return 1+(L>R? L:R);
	}
	void Inorder(BRTreeNode*node)
	{
		if(node!=nil)
		{
			Inorder(node->left);
			cout<<node->key<<" ";
			Inorder(node->right);
		}
	}
	void Preorder(BRTreeNode*node)
	{
		if(node!=nil)
		{
			cout<<node->key<<" ";
			Preorder(node->left);
			Preorder(node->right);
		}
	}
	void Posetorder(BRTreeNode*node)
	{
		if(node!=nil)
		{
			Posetorder(node->left);
			Posetorder(node->right);
			cout<<node->key<<" ";
		}
	}
	//层次法打印树
void DispTree(BRTreeNode*BT)
{
    BRTreeNode stack[maxSize],p;
    int level[maxSize][2],top,n,i,width=4;
    if(BT!=NULL)
    {
        cout<<"Display a tree by hollow means."<<endl;
        top=1;
        stack[top]=BT;//push root point to stack.
        level[top][0]=width;
        while(top>0)
        {
            p=stack[top];
            n=level[top][0];
            for(i=1;i<=n;i++)
                cout<<" ";
            //输出信息
            if(p.key==0)
            {
                cout<<")";
            }
            else{
            if(p.key==-1) cout<<"Nil";
            else if(p.left&&p.right) cout<<"("<<p.key;
            else cout<<p.key;
            if(p.Getcolor()) cout<<"R,";
            else cout<<"B,";
            }
            for(i=n+1;i<maxWidth;i+=2)
                cout<<"--";
            cout<<endl;
            top--;
            if(p.right!=NULL)
            {
                //插入一个括号节点,key值为0
                top++;
                BRTreeNode* tmp=new BRTreeNode();
                tmp->key=0;
                stack[top]=tmp;
                level[top][0]=n+width;
                level[top][1]=2;
                top++;
                stack[top]=p.right;
                level[top][0]=n+width;
                level[top][1]=2;

            }
            if(p.left!=NULL)
            {
                top++;
                stack[top]=p.left;
                level[top][0]=n+width;
                level[top][1]=1;
            }
        }
    }
}
	//左旋节点node
	bool LeftRotate(BRTreeNode* node)
	{
		BRTreeNode*y;
		if(node->right==nil)
		{
			cout<<"can't left rotate!"<<endl;
			return 0;
		}
		y=node->right;
		node->right=y->left;
		if(y->left!=nil)
		{
			y->left->parent=node;
		}
		y->parent=node->parent;
		if(node->parent==nil)
		{
			root=y;
		}
		else if(node->parent->left==node)
		{
			node->parent->left=y;
		}
		else
		{
			node->parent->right=y;
		}
		y->left=node;
		node->parent=y;
		return 1;
	}
	//右旋节点
	bool RightRotate(BRTreeNode* node)
	{
		if(node->left==nil)
		{
			cout<<"can't rightrotate!"<<endl;
			return 0;
		}
		BRTreeNode* x;
		x=node->left;
		node->left=x->right;
		if(x->right!=nil)
		{
			x->right->parent=node;
		}
		x->parent=node->parent;
		if(node->parent==nil)
		{
			root=x;
		}
		else if(node->parent->left==node)
		{
			node->parent->left=x;
		}
		else
		{
			node->parent->right=x;
		}
		node->parent=x;
		x->right=node;
		return 1;
	}
	void Insert(int num)
	{
		BRTreeNode* node=new BRTreeNode(num,1);
		node->left=nil;
		node->right=nil;
		node->parent=nil;
		BRTreeNode* p=root,*q=nil;
		if(root==nil)
		{
			node->color=0;
			root=node;
			root->left=root->right=root->parent=nil;
			return ;
		}
		while(p!=nil)
		{
			if(p->key==num)
			{
				cout<<num<<"  has exist!"<<endl;
				return ;
			}
			else if(p->key>num)
			{
				q=p;
				p=p->left;
			}
			else
			{
				q=p;
				p=p->right;
			}
		}
		if(q->key>num)
		{
			q->left=node;
			node->parent=q;
		}
		else
		{
			q->right=node;
			node->parent=q;
		}
		RBInsertAdjust(node);
	}
	void RBInsertAdjust(BRTreeNode* node)
	{
		BRTreeNode* y;
		while(node->parent->color==1)
		{
			if(node->parent==node->parent->parent->left)
			{
				y=node->parent->parent->right;
				if(y->color==1)
				{
					node->parent->color=0;
					y->color=0;
					y->parent->color=1;
					node=node->parent->parent;
				}
				//此时y的颜色是黑色
				else
				{
					//第二种情况
					if(node==node->parent->right)
					{
						node=node->parent;
						LeftRotate(node);
					}
					//第三种情况
					node->parent->color=0;
					node->parent->parent->color=1;
					RightRotate(node->parent->parent);
				}
			}
			else
			{
				y=node->parent->parent->left;
				if(y->color==1)
				{
					node->parent->color=0;
					y->color=0;
					y->parent->color=1;
					node=node->parent->parent;
				}
				else
				{
					if(node==node->parent->left)
					{
						node=node->parent;
						RightRotate(node);
					}
					node->parent->color=0;
					node->parent->parent->color=1;
					LeftRotate(node->parent->parent);
				}
			}
		}
		root->color=0;
	}
	BRTreeNode* Search(int num)
	{
		BRTreeNode* p=root;
		while(p!=nil)
		{
			if(p->key==num)
			{
				return p;
			}
			else if(p->key>num)
			{
				p=p->left;
			}
			else
			{
				p=p->right;
			}
		}
		cout<<"there is no "<<num<<" in this tree!"<<endl;
		return nil;
	}
	//获取以node节点为根节点的树的最小元素,并返回该最小值
	int Minnum(BRTreeNode*node)
	{
		BRTreeNode*p=node;
		while(p->left!=nil)
		{
			p=p->left;
		}
		return p->key;
	}
	//获取以node节点为根节点的树的最da元素,并返回该最da值
	int Maxnum(BRTreeNode*node)
	{
		BRTreeNode*p=node;
		while(p->right!=nil)
		{
			p=p->right;
		}
		return p->key;
	}
	//获取以node节点为根节点的树的最小元素,并返回该节点
	BRTreeNode* MinNum(BRTreeNode*node)
	{
		BRTreeNode*p=node;
		while(p->left!=nil)
		{
			p=p->left;
		}
		return p;
	}
	//获取以node节点为根节点的树的最大元素
	BRTreeNode* MaxNum(BRTreeNode*node)
	{
		BRTreeNode*p=node;
		while(p->right!=nil)
		{
			p=p->right;
		}
		return p;
	}
	BRTreeNode*InorderSuccessor(BRTreeNode*node)
	{
		if(node->right!=nil)
		{
			return MinNum(node->right);
		}
		else
		{
			BRTreeNode*p=GetParent(node);
			while(p&&node==p->right)
			{
				node=p;
				p=GetParent(node);
			}
			return p;
		}
	}
	//中序遍历的前趋
	BRTreeNode*InordePredecessor(BRTreeNode*node)
	{
		if(node->left!=nil)
		{
			return MaxNum(node->left);
		}
		else
		{
			BRTreeNode*p=GetParent(node);
			while(p&&node==p->left)
			{
				node=p;
				p=GetParent(node);
			}
			return p;
		}
	}
	bool Delete(int num)
	{
		BRTreeNode*z,*y,*x;
        //寻找key值为num的节点p
        z=Search(num);
		//如果没有该节点则返回0
        if(z==nil)
        {
            return 0;
        }
		if(z->left==nil||z->right==nil)
		{
			y=z;
		}
		else
			y=InorderSuccessor(z);
		if(y->left!=nil)
			x=y->left;
		else
			x=y->right;
		x->parent=y->parent;
		if(x->parent==nil)
			root=x;
		else if(y=y->parent->left)
			y->parent->left=x;
		else
			y->parent->right=x;
		if(y!=z)
		{
			z->key=y->key;
		}
		if(y->color==0)
		{
			RBTreeFixup(x);
		}
		return 1;
	}
	void RBTreeFixup(BRTreeNode* x)
	{
		BRTreeNode*w;
		while(x!=root&&x->color==0)
		{
			if(x==x->parent->left)
			{
				w=x->parent->right;
				if(w->color==1)
				{
					w->color=0;
					x->parent->color=1;
					LeftRotate(x->parent);
					w=x->parent->right;
				}
				if(w->left->color==0&&w->right->color==0)
				{
					w->color=1;
					x=x->parent;
				}
				else
				{
					if(w->right->color==0)
					{
						w->color=1;
						RightRotate(w);
						w=x->parent->right;
					}
					w->color=x->parent->color;
					x->parent->color=0;
					w->right->color=0;
					LeftRotate(x->parent);
					x=root;
				}
			}
			else
			{
				w=x->parent->left;
				if(w->color==1)
				{
					w->color=0;
					x->parent->color=1;
					RightRotate(x->parent);
					w=x->parent->left;
				}
				if(w->right->color==0&&w->left->color==0)
				{
					w->color=1;
					x=x->parent;
				}
				else
				{
					if(w->left->color==0)
					{
						w->color=1;
						LeftRotate(w);
						w=x->parent->left;
					}
					w->color=x->parent->color;
					x->parent->color=0;
					w->left->color=0;
					RightRotate(x->parent);
					x=root;
				}
			}
		}
		x->color=0;
	}
};

#endif // BRTREE_H_INCLUDED

测试程序

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

int main()
{
    BRTree tree;
    cout<<"Insert 9 numbers:"<<endl;
    int a[9]={8,11,17,15,6,1,22,25,27};
    int i;
    for(i=0;i<9;i++)
    {
        tree.Insert(a[i]);
    }
    tree.DispTree(tree.Getroot());
    cout<<"Delete 11:"<<endl;
    tree.Delete(11);
    tree.DispTree(tree.Getroot());
    cout << "blackHeight:" <<tree.GetBlackHeight(tree.Getroot())<<endl;

    return 0;
}


运行结果:




参考:

教你透彻了解红黑树-http://blog.csdn.net/v_JULY_v/article/details/6105630



算法导论 之 红黑树 - 插入[C语言]

一、性质分析 1.1 性质定义     红黑树是一种二叉查找树,但在每个节点上增加一个存储位表示节点的颜色[RED或BLACK]。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路...
  • RoyalApex
  • RoyalApex
  • 2013年12月24日 21:31
  • 3262

算法导论--红黑树

红黑树是平衡搜索树的一种,可以保证在最坏情况下基本动态集合操作的时间复杂度为Lgn。红黑树在二叉搜索树的基础上结点增加了一个属性color,值为black或者red,即一个节点的属性有:left,ri...
  • luoshixian099
  • luoshixian099
  • 2015年05月17日 09:29
  • 3504

算法导论学习--红黑树详解之删除(含完整红黑树代码)

前面我们讨论了红黑树的插入的实现,基本思想是分类讨论;然后分情况讨论以后我们发现插入操作调整函数只需要处理三种情况,并不是太复杂。但是删除操作会更复杂一点,因为二叉搜索树的删除操作本身就分成了多种情况...
  • acm_lkl
  • acm_lkl
  • 2015年07月06日 20:05
  • 2325

【算法导论】红黑树详解之一(插入)

红黑树是建立在二叉查找树的基础之上的,关于二叉查找树可以参看【算法导论】二叉搜索树的插入和删除和【算法导论】二叉树的前中后序非递归遍历实现。对于高度为h的二叉查找树而言,它的SEARCH、INSERT...
  • cyp331203
  • cyp331203
  • 2015年01月14日 11:11
  • 3597

算法导论13.1红黑树的性质 练习总结

13.1-1 按照图13-1(a) 的方式,画出关键字集合{1,2,... ,15 }上高度为 3 的完全二叉搜索树。以三种不同方式想图中加入 NIL 叶结点并对各结点着色,使所得的红黑树的黑高分别为...
  • chan15
  • chan15
  • 2015年10月10日 16:57
  • 1414

C++ 红黑树的实现

红黑树性质及实现详细介绍: http://zh.wikipedia.org/zh/%E7%BA%A2%E9%BB%91%E6%A0%91 代码部分:  头文件 // RBTree.h: int...
  • xgx198831
  • xgx198831
  • 2012年03月09日 08:52
  • 6508

算法导论-13-2-红黑树上的连接操作

题目:(cd还有些疑问) 答: a)黑高度增加的唯一方式是插入时黑色传到root且root原先为红色然后然后变为黑色。黑高度减少的唯一方式是额外的黑色传到root节点。因此可以在插入和删除...
  • mishifangxiangdefeng
  • mishifangxiangdefeng
  • 2012年08月24日 17:55
  • 6028

红黑树的C++实现与解析

所谓红黑树,就是平衡的扩充二叉搜索树,红黑树与AVL都是BST的平衡版本,相比AVL的完全平衡,红黑树只要求局部平衡,因此当向红黑树中插入和删除节点时,需要的调整比AVL要少,统计性能要好于AVL树,...
  • wang11chao01
  • wang11chao01
  • 2012年07月27日 16:06
  • 6601

算法导论 之 红黑树 - 删除[C语言]

作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客:http://blog.csdn.net/qifengzou 日期:2014.01.18 01:21 转载请...
  • RoyalApex
  • RoyalApex
  • 2014年01月18日 01:28
  • 2706

学习 《算法导论》第13章 红黑树 总结二

学习 《算法导论》第13章 红黑树 总结二在学习 《算法导论》第13章 红黑树 总结一中学习了红黑树的五个性质,红黑树的结构定义以及旋转。这节学习红黑树的插入和删除操作。红黑树的插入在一棵n个结点的红...
  • wan198809
  • wan198809
  • 2015年09月20日 21:26
  • 392
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法导论-红黑树C++实现
举报原因:
原因补充:

(最多只允许输入30个字)