您的位置:首页 > 其它

红黑树(Red BlackTree)的实现

2012-09-04 12:41 591 查看
前面我们讲解了简单二叉查找树、AVL树,伸展树,对于一棵高度为h的二叉查找树,其动态集合操作Search、Minimum、Maximum、Successor、Predecessor、Insert、Delete的运行时间为θ(h),树的高度决定了在树上操作的成本。

一些常见的搜索树的高度:

平衡二叉搜索树:O(lgn)

1962年提出的AVL树:<=1.44lgn

1972年提出的红黑树:<=2lg(n+1)

红黑树是通过对二叉查找树结点上增加一个存储位表示结点的颜色(红色或黑色) 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路径会比其他路径长出两倍,从而接近平衡。

一、红黑树的性质

1、红黑树的定义

红黑树是满足如下性质的二叉查找树:

(1) 每个结点必须为红色或黑色。

(2) 根为黑色。

(3) 树中的nil叶子为黑色。

(4) 若结点为红,则其两个子孩子必为黑。

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

2、黑高度

从某个结点x出发(不包括该结点)到达一个叶结点的任意一条路径上,黑色结点的个数称为该结点x的黑高度,用bh(x)表示。

3、红黑树的黑高度

红黑树的黑高度定义为其根结点的黑高度,记为bh(root[T]).。

4、红黑树的高度

一棵含n个内结点的红黑树的高度至多为2lg( n+1) 。(证明请看算法导论)

二、红黑树的实现

1、原理请看参考资料[1]、[2]、[3]

2、下面给出的C++实现是完全按照算法导论上的伪代码来的。参考资料[4]中给出了自顶向下红黑树的部分实现(未提供删除操作),采用的是不含父节点指针的结点结构,但是实现复杂,不是很好理解。

3、实现代码

#include <cstdlib>
#include <iostream>

using namespace std;

template <typename Comparable>
class RBTree
{
public:

RBTree()
{
nil = new RBTreeNode;//哨兵结点为黑色
nil->parent = nil;
nil->lchild = nil;
nil->rchild = nil;
root = nil;
}
~RBTree()
{
makeEmpty(root);
delete nil;
}

void preOrderTraverse()const
{
preOrderTraverse(root);
}

void inOrderTraverse()const
{
inOrderTraverse(root);
}

void printTree()const
{
cout<<"preOrder :"<<endl;
preOrderTraverse();
cout<<endl;

cout<<"inOrder :"<<endl;
inOrderTraverse();
cout<<endl<<endl;
}

//将元素插入红黑树中
bool insert(const Comparable& elem)
{
RBTreeNode* y = nil;	//y记录当前结点的父结点
RBTreeNode* x = root;		//从根结点开始扫描,寻找插入点

while(x != nil)
{
y = x;
if(elem < x->data)	//当前结点左子树中继续扫描
{
x = x->lchild;
}
else if(x->data < elem)
{
x = x->rchild;	//当前结点右子树中继续扫描
}
else
{
return false;			//树中已存在该元素
}
}
//准备插入该元素
RBTreeNode* z = new RBTreeNode(elem);
z->parent = y;					//y是z的双亲
if(y == nil)					//z插入空树
{
root = z;						//z为新的根结点
}
else if(elem < y->data)
{
y->lchild = z;				//z为y的左孩子
}
else
{
y->rchild = z;				//z为y的右孩子
}
z->lchild = nil;
z->rchild = nil;
z->color = RED;
insertFixup(z);					//插入后调整
return true;
}

//从红黑树中删除一个元素
bool remove(const Comparable& elem)
{
RBTreeNode* z = search(elem, root);//查找结点
RBTreeNode* y;		//y为要删除的结点
RBTreeNode* x;		//y的孩子结点

if(z != nil)
{
if(z->lchild == nil || z->rchild == nil)//case1 2
{
y = z;
}
else	//左右子树均不空 case 3
{
y = successor(z);//后继y的左子树必然为空(nil)
}
//确定y的孩子结点(待连接到p[y])
if(y->lchild != nil)
{
x = y->lchild;
}
else
{
x = y->rchild;
}

x->parent = y->parent;
if(y->parent == nil)//y为根结点
{
root = x;
}
else if(y == y->parent->lchild)
{
y->parent->lchild = x;
}
else
{
y->parent->rchild = x;
}

if(y != z)//case 3
{
z->data = y->data;
}

if(y->color == BLACK)//删除结点为黑色,重新调整
{
removeFixup(x);
}

delete y;
return true;
}
return false;				//树中不存在该结点
}

bool search(const Comparable& elem)const
{
if(search(elem, root)!= nil)
{
return true;
}
return false;
}

bool isEmpty()
{
return root == nil;
}

/*求某一元素的后继,前驱类似
*应该确保树非空,且树中存在该元素
否则抛出异常(这里不做处理)
*/
Comparable successor(const Comparable& elem)
{
RBTreeNode* z = search(elem, root);//查找结点
if(z != nil)
{
return z->data;
}
//			else
//			{
//				throw exception;
//			}
}

private:

enum COLOR{BLACK,RED};

struct RBTreeNode
{
COLOR color;					//结点颜色
Comparable data;				//结点数据
struct RBTreeNode* parent;	//父节点指针
struct RBTreeNode* lchild;	//左孩子结点指针
struct RBTreeNode* rchild;	//右孩子结点指针

RBTreeNode(): color(BLACK),data(Comparable()),
parent(NULL),lchild(NULL),rchild(NULL){}
RBTreeNode(const Comparable& elem ): color(BLACK),data(elem),
parent(NULL),lchild(NULL),rchild(NULL){}
};
//========================================
RBTreeNode * root;				//根结点
RBTreeNode * nil;				//哨兵结点
//========================================

void leftRotate(RBTreeNode* x)	//左旋
{
RBTreeNode* y = x->rchild;
x->rchild = y->lchild;
if(y->lchild != nil)
{
y->lchild->parent = x;
}
y->parent = x->parent;
if(x->parent == nil)
{
root = y;				//y为新的根结点
}
else if(x == x->parent->lchild)
{
x->parent->lchild = y;
}
else
{
x->parent->rchild = y;
}
y->lchild = x;
x->parent = y;
}

void rightRotate(RBTreeNode* x)//右旋
{
RBTreeNode* y = x->lchild;
x->lchild = y->rchild;
if(y->rchild != nil)
{
y->rchild->parent = x;
}
y->parent = x->parent;
if(x->parent == nil)
{
root = y;
}
else if(x == x->parent->lchild)
{
x->parent->lchild = y;
}
else
{
x->parent->rchild = y;
}
y->rchild = x;
x->parent = y;
}

//插入之后的修复操作
void insertFixup(RBTreeNode* z)
{
RBTreeNode* y;				//y是z的叔父结点
while(z->parent->color == RED)
{
//z的父结点是z的祖父结点的左孩子
if(z->parent == z->parent->parent->lchild)
{
//case 1 2 3
y = z->parent->parent->rchild;
if(y->color == RED)
{
//case1
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else //case2 or case 3 ,y->color == BLACK
{
//case2
if(z == z->parent->rchild)
{
z = z->parent;		//z上溯至父节点
leftRotate(z);		//左旋
}
//case3
z->parent->color = BLACK;
z->parent->parent->color = RED;
rightRotate(z->parent->parent);
}
}
else//case 4,5,6与上面对称
{
y = z->parent->parent->lchild;
if(y->color == RED)
{
//case4
z->parent->color = BLACK;
y->color = BLACK;
z = z->parent->parent;
}
else//case 5 or case 6
{
//case 5
if(z == z->parent->lchild)
{
z = z->parent;
rightRotate(z);
}
//case 6
z->parent->color = BLACK;
z->parent->parent->color = RED;
leftRotate(z->parent->parent);
}
}
}
root->color = BLACK;
}

//删除之后的修复操作
void removeFixup(RBTreeNode* x)
{
RBTreeNode* w;			//x的兄弟结点

while(x != root && x->color == BLACK)
{
if(x == x->parent->lchild)//case1-4
{
w = x->parent->rchild;
if(w->color == RED)
{
//case1
w->color = BLACK;
x->parent->color = RED;
leftRotate(x->parent);
w = x->parent->rchild;
}

//w->color == BLACK
if(w->lchild->color == BLACK && w->rchild->color == BLACK)
{
//case 2
w->color = RED;
x = x->parent;//
}
else
{
//case 3
if(w->rchild->color == BLACK)//左子为RED
{
w->lchild->color = BLACK;
w->color = RED;
rightRotate(w);
w = x->parent->rchild;
}
//case 4 右子为RED
w->color = x->parent->color;
x->parent->color = BLACK;
w->rchild->color = BLACK;
leftRotate(x->parent);
x = root;
}
}
else//case5-8,和上面对称
{
w = x->parent->lchild;
if(w->color == RED)
{
//case 5
w->color = BLACK;
x->parent->color = RED;
rightRotate(x->parent);
w = x->parent->lchild;
}

//w->color == BLACK
if(w->lchild->color == BLACK && w->rchild->color == BLACK)
{
//case 6
w->color = RED;
x = x->parent;//
}
else
{
//case 7
if(w->lchild->color == BLACK)//右子为RED
{
w->rchild->color = BLACK;
w->color = RED;
leftRotate(w);
w = x->parent->lchild;
}
//case 8 左子为RED
w->color = x->parent->color;
x->parent->color = BLACK;
w->lchild->color = BLACK;
rightRotate(x->parent);
x = root;
}
}
}

x->color = BLACK;
}

//在以t为根的红黑树中查找给定元素
//返回相应的结点指针
RBTreeNode* search(const Comparable& elem, RBTreeNode* t)const
{
while(t != nil && elem != t->data)
{
if(elem < t->data)
{
t = t->lchild;
}
else if(t->data < elem)
{
t = t->rchild;
}
}
return t;
}

//求结点x的中序后继结点
RBTreeNode* successor(RBTreeNode* x)
{
RBTreeNode* y;

if(x->rchild != nil)
{
y = x->rchild;
while(y->lchild != nil)
{
y = y->lchild;
}
}
else
{
y = x->parent;
while(y != nil && x == y->rchild)
{
x = y;
y = y->parent;
}
}
return y;
}

//前序遍历
void preOrderTraverse(RBTreeNode* t)const
{
if(t != nil)
{
cout<<"("<<t->data<<",";
t->color ?  cout<<"RED" : cout<<"BLACK";
cout<<")";
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
}
}

//中序遍历
void inOrderTraverse(RBTreeNode* t)const
{
if(t != nil)
{
inOrderTraverse(t->lchild);
cout<<"("<<t->data<<",";
t->color ?  cout<<"RED" : cout<<"BLACK";
cout<<")";
inOrderTraverse(t->rchild);
}
}

//销毁红黑树
void makeEmpty(RBTreeNode* t)
{
if(t != nil)
{
makeEmpty(t->lchild);
makeEmpty(t->rchild);
delete t;
t = NULL;
}
}
};

int main(int argc, char *argv[])
{
RBTree<int> rbtree;
const int N = 6;
//insert
for(int i=1; i<N;i++)
{
rbtree.insert(i);
cout<<"after insert "<<i<<":"<<endl;
rbtree.printTree();
}

//search
cout<<"search: "<<endl;
for(int i=1; i<N;i++)
{
cout<<"("<<i<<","<<rbtree.search(i)<<")";
}
cout<<endl<<endl;

//remove
for(int i=1; i<N; i += 2)
{
rbtree.remove(i);
cout<<"after remove: "<<i<<endl;
rbtree.printTree();
}

//search
cout<<"search: "<<endl;
for(int i=1; i<N;i++)
{
cout<<"("<<i<<","<<rbtree.search(i)<<")";
}
cout<<endl<<endl;

system("PAUSE");
return EXIT_SUCCESS;
}


参考资料:
[1]算法导论(第2版)第13章P163-P176

[2]红黑树及扩张:http://wenku.baidu.com/view/673d3e6eb84ae45c3b358c29.html

[3]博客文章(C#实现):/content/3959184.html

[4]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )

[5]文章(C++实现):http://www.linuxidc.com/Linux/2012-01/52530.htm

[6]文章(C实现):http://www.chinaunix.net/old_jh/23/1308846.html

[7]C语言实现:http://wenku.baidu.com/view/1187190390c69ec3d5bb7544.html

[8]红黑树的实现与讨论:http://www.cppblog.com/daly88/archive/2009/11/20/101519.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: