红黑树

理论知识参见 《数据结构基础 》 张力译版

以下代码与大家分享,如有错误之处希望批评指正。(我已测试通过)

//RedBlackTree.h
#ifndef _REDBLACKTREE_
#define _REDBLACKTREE_
class TreeNode
{
	friend class RedBlackTree;
public:
	TreeNode(int e)
	{
		key=e;
		rb=0;
		leftchild=rightchild=0;
	}
private:
	int key;
	bool rb;//颜色标记0 红 1 black
	TreeNode *leftchild, *rightchild;
};
class RedBlackTree
{
public:
	RedBlackTree(TreeNode* init=0)
	{
		root=0;
	}
	void Insert(const int e);
	
private:
	TreeNode * root;
};
#endif



//RedBlackTree.cpp

#include "RedBlackTree.h"
#include <iostream>
#include <stack>
using namespace std;
void RedBlackTree::Insert(const int e)
{
	if (!root)
	{
		root=new TreeNode(e);
		root->rb=1;//根节点始终是黑色
		return ;
	}
	stack<TreeNode*>s;//记录遍历路径
	TreeNode *u=root;
	TreeNode *pu=0;//u的父节点
	TreeNode *gu=0;//u的祖父节点
	TreeNode *uu=0;//叔父节点
	while(u)//查找插入位置
	{
		s.push(u);
		/*关键字查找*/
		if (e==u->key)//已有该关键字 
		{
			return;
		}
		else if (e<u->key)
		{
			u=u->leftchild;
		}
		else 
		{
			u=u->rightchild;
		}
	}
	bool inflag=0; //新节点尚未插入
	u=new TreeNode(e);
	pu=s.top();//得到父节点
		s.pop();
	while (1)//一直进行
	{
		
		if (s.empty())//s空 仅有父节点 
		{
			//无祖父节点
			if (!inflag)// 尚未插入
			{
				if (e<pu->key)
				{
					pu->leftchild=u;	
				}
				else if (e>pu->key)
				{
					pu->rightchild=u;
				}
				inflag=1;
			}
			return ;
		}
		else
		{
			gu=s.top();
			s.pop();
			//尚未插入则插入
			if (!inflag)// 尚未插入
			{
				if (e<pu->key)
				{
					pu->leftchild=u;	
				}
				else if (e>pu->key)
				{
					pu->rightchild=u;
				}
				inflag=1;
			}
			//判断当前的u是否违反性质2  不违反则返回,违反则分类操作
			if (pu->rb!=u->rb)//不违反性质2
			{
				return;
			}
			else
			{
				//分类 r b
				if (pu==gu->leftchild)
				{
					uu=gu->rightchild;
				} 
				else
				{
					uu=gu->leftchild;
				}
				
				if (uu&&uu->rb==0)//red 颜色变换   LL 与RL 变换相同
				{
					if (gu->leftchild==pu)//1L
					{
					//	if (pu->leftchild==u)//2L  (LL)
					//	{
							//LLr  颜色变换
							gu->rb=0;
							uu->rb=1;
							pu->rb=1;

					//	}
					//	else//2R (LR)
					//	{
					//		gu->rb=0;
					//		uu->rb=1;
					//		pu->rb=1;
					//	}
					} 
					else//1R
					{
					//	if (pu->leftchild==u)//2L  (RL)
				//		{
							//RLr  颜色变换
							gu->rb=0;
							uu->rb=1;
							pu->rb=1;
					//	}
					//	else//2R (RR)
					//	{
					//		gu->rb=0;
					//		uu->rb=1;
					//		pu->rb=1;
					//	}
					}
					u=gu;//准备下次判断、操作
					if (!s.empty())
					{
						pu=s.top();
						s.pop();
					}
					else
					{
						u->rb=1;//root
					}
				}
				else// b 旋转
				{
					if (gu->leftchild==pu)//1L
					{
						if (pu->leftchild==u)//2L  (LL)
						{
							//LLb  旋转
							gu->leftchild=pu->rightchild;
							pu->rightchild=gu;
							pu->rb=1;
							gu->rb=0;
						}
						else//2R (LRb)
						{
							gu->leftchild=u->rightchild;
							pu->rightchild=u->leftchild;
							u->leftchild=pu;
							u->rightchild=gu;
							u->rb=1;
							gu->rb=0;
							pu->rb=0;
						}
					} 
					else//1R
					{
						if (pu->leftchild==u)//2L  (RL)
						{
							//RLb  旋转
							pu->leftchild=u->rightchild;
							gu->rightchild=u->leftchild;
							u->rightchild=pu;
							u->leftchild=gu;
							u->rb=1;
							gu->rb=0;
							pu->rb=0;
						}
						else//2R (RR)
						{
						
							gu->rightchild=pu->leftchild;
							pu->leftchild=gu;
							pu->rb=1;
							gu->rb=0;
						}
					}
					if (!s.empty())
					{
						pu=s.top();
						s.pop();
					}
					else
					{
						root=u;
						u->rb=1;//root
						return;
					}
					if (e<pu->key)
					{
						pu->leftchild=u;
					}
					else
					{
						pu->rightchild=u;
					}
					return;
				}
			}	
		}
	}	
}

//main.cpp
#include <iostream>
#include "RedBlackTree.h"
using namespace std;
void main()
{
	RedBlackTree rbt;
	rbt.Insert(50);
	rbt.Insert(10);
	rbt.Insert(80);
    rbt.Insert(90);
	rbt.Insert(70);
	rbt.Insert(60);
	rbt.Insert(65);
	rbt.Insert(62);
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值