在查找中,虽然hash表查找非常迅速,但是随着数据的种类增多,
hash表长会变得更长,且冲突也会越来越多,那么如何能实现无论在
多大数据量的情况下,查找依然是高性能的呢?
在1978年,Leo J.Guibas 与 Robert Sedgewick写了一篇论文中
谈到了一种较好的用于查找的数据结构----红黑树
一般来说,树是很好的一种数据结构,那用于插入,删除,查找等
都是很高效的数据树构,但问题是在很坏的情况下,操作很费时间,它的
性能得到不保证,比如二叉查找树中如果左子树与右子树相差太远,那么查找
时就很费时间。这时为了保证其有高效性,就得保证左树与右树不能差得太远,
当向树中插入时,就按一定规则调整,使其达到规则,从而使其整体与局部
查找效率得到提高。这就是红黑树的规则.
这些规则是
在二叉查找树的基础上,
(1)节点都有颜色,要么黑色,要么红色。
(2)根结点是黑色的,叶子结点是黑色的。
(3)每条从树到叶子的路上没有二个连续的红色。即红色的子树一定是黑色
(4)各条从叶子到根的路上的黑色结点相同。
关键的是(3), (4)它使得树是局部是平衡的,并且每条路线不会太长。
还有一个重要的点就是,为了研究方便,会在红黑树补成两个子树是完整的,
它们也有颜色,是黑色,但是没有数据,它称为nil叶子,null叶子。当搜索时
发现结点与nil叶子相 等时,则是找到了叶子了。
另外,关于红黑树与平衡二叉树的区别,它们的区别在概念上也有,
但是在性能上也有,平衡二叉树也是在最坏的情况下有高效的,但是它
追求整体的平衡,使得调整树时,会要很长的时间复杂度,而红黑树是
局部平衡,调整时只要0(logn)颜色变量,并且调整不超过三次。
那么如何使用红黑树来解决问题呢,可以先构造红黑树
构造红黑树的办法如下:
(1)定义节点结构,
一般是 值,key, 长度,左指针,右指针,指向父的指针,颜色。
(2)插入
插入时,先从树根开始,先校验树是不是为空节点或者nil结点,若是
则插入结点为新根,若不是,则与树比较,小于的话,往左移,大于
往右移,这里与二叉查找树类似,最后再对其颜色进行调整.所谓的调
整只有4种情况,都设计好了。
(3)查找
按照二叉查找树的样子进行查找。
例子:查找班上姓名为'xiaoming'同学的基本信息情况
办法: 则要以姓名为关键字建立一个红黑树,建法很多,
可以以其各字母ascii和的办法作为关键字,或以某函数生成一个均可。
然后树据关键字的值生成红黑树,再查找就可以了
部分MFC代码如下:
节点结构。
typedef struct Node
{
Coulor color;
int key;
Node *p,*left,*right;
int size;
char *name; //the description data that the node contained
}Node,*pNode;
下面的代码中,rbInsert(pNode z)为插入创建的函数,
void rbInsertFixUp(pNode z)为调整局部色彩的函数。
------------------
//RBTree.h文件如下
#ifndef RBTREE_H
#define RBTREE_H
#pragma once
#include
#include"MainFrm.h"
enum Coulor{RED,BLACK};
typedef struct Node
{
Coulor color;
int key;
Node *p,*left,*right;
int size;
char *name; //the description data that the node contained
}Node,*pNode;
extern Node Nil; //ÉÚ±ø
extern const pNode nil;
class rbTree
{
public:
pNode root;
pNode cur;
public:
rbTree(){root=cur=&Nil;};
void setName(pNode x,const char*na)
{
x->name=new char[strlen(na)+1];
strcpy(x->name,na);
}
pNode newNode(int k,const char*na="N",pNode pa=nil,pNode le=nil,pNode ri=nil)
{
pNode ne=new Node;
ne->key=k;
ne->color=RED;
ne->left=le;
ne->p=pa;
ne->right=ri;
ne->size=1;
setName(ne,na);
return ne;
}
//·ÃÎÊp,left,rightµÈ
pNode &p(pNode x){return x->p;};
pNode &left(pNode x){return x->left;};
pNode &right(pNode x){return x->right;};
int &size(pNode x){return x->size;};
Coulor &color(pNode x){return x->color;};
int &key(pNode x){return x->key;};
//
const pNode P(pNode x){return x->p;};
const pNode Left(pNode x){return x->left;};
const pNode Right(pNode x){return x->right;};
const int Size(pNode x){return x->size;};
const Coulor Color(pNode x){return x->color;};
const int Key(pNode x){return x->key;};
pNode successor(pNode x)
{
if(Right(x) != nil)
return minimum(Right(x));
pNode y= P(x);
while ( y!=nil && x==Right(y) )
{
x=y;
y=P(y);
}
return y;
}
//
pNode minimum( pNode x)
{
while (Left(x)!=nil)
x=Left(x);
return x;
}
int Bheight(pNode x)
{
pNode y=x;
int k=0;
while(y!=nil)
{
if(Color(y)==BLACK)
k++;
y=Left(y);
}
return k;
}
//×óÐýת
void lrotate(pNode x)
{
pNode y=Right(x);
//ά»¤size;
int sx=x->size;
int sy=y->size;
size(y)=sx;
size(x)=sx-size(Right(y))-1;
right(x)=Left(y);
p(Left(y))=x;
p(y)=P(x);
if(P(x)==nil)
{
root=y;
}
else if( x == Left(P(x)) )
{
left(P(y))=y;
}
else
right(P(x))=y;
left(y)=x;
p(x)=y;
}
//ÓÒÐýת
void rrotate(pNode x)
{
pNode y=Left(x);
//ά»¤size;
size(y)=Size(x);
size(x)=Size(x)-Size(Left(y))-1;
left(x)=Right(y);
p(Right(y))=x;
p(y)=P(x);
if(P(x)==nil)
{
root=y;
}
else if(x==Left(P(x)))
{
left(P(y))=y;
}
else
right(P(x))=y;
right(y)=x;
p(x)=y;
}
///
//²åÈë¼°Æäµ÷Õû
//²åÈë
void rbInsert(pNode z)
{
pNode y=nil;
pNode x=root;
while(x!=nil)
{
y=x;
size(x)=Size(x)+1;
if(Key(z) < Key(x))
x=Left(x);
else
x=Right(x);
}
p(z)=y;
if(y == nil)
root=z;
else if(Key(z)
left(y)=z;
else
right(y)=z;
rbInsertFixUp(z);
}
//µ÷Õû
void rbInsertFixUp(pNode z)
{
while(Color(P(z)) == RED)
{
if( P(z) == Left(P(P(z))))
{
pNode y=Right(P(P(z)));
if(Color(y) == RED)
{
color(P(z)) = BLACK;
color(y)= BLACK;
color(P(P(z))) =RED;
z=P(P(z));
}
else
{
if(z == Right(P(z)))
{
z=P(z);
lrotate(z);
}
color(P(z))=BLACK;
color(P(P(z)))=RED;
rrotate(p(P(z)));
}
}
else
{
pNode y=Left(P(P(z)));
if(Color(y) == RED)
{
color(P(z)) = BLACK;
color(y)= BLACK;
color(P(P(z))) =RED;
z=P(P(z));
}
else
{
if(z == Left(P(z)))
{
z=P(z);
rrotate(z);
}
color(P(z))=BLACK;
color(P(P(z)))=RED;
lrotate(p(P(z)));
}
}
}
color(root)=BLACK;
}
//
//ɾ³ý¼°Æäµ÷Õû
//ɾ³ý
pNode rbDelete(pNode z)
{
pNode x,y;
if(Left(z) == nil ||Right(z)==nil)
y=z;
else
y=successor(z);
if(Left(y) !=nil)
x=Left(y);
else
x=Right(y);
p(x)=P(y);
if(P(y) ==nil)
root=x;
else if(y==Left(P(y)) )
left(P(y))=x;
else
right(P(y))=x;
if(y!=z)
{
key(z)=Key(y);//
}
rbDeleteMaitainSize(y);
if(Color(y)==BLACK)
rbDeleteFixUp(x);
return y;
}
//µ÷Õû
void rbDeleteFixUp(pNode x)
{
while(x!=root && Color(x)==BLACK)
{
if(x ==Left(P(x)) )
{
pNode w=Right(P(x));
//case1
if(Color(w)==RED)
{
color(w)=BLACK;
color(P(x))=RED;
lrotate(P(x));
w=Right(P(x));
}
//case 2,3,4
if(Color(Left(w))==BLACK && Color(Right(w)) ==BLACK)
{
color(w)=RED;
x=P(x);
}
else if(Color(Right(w)) == BLACK)
{
color(Left(w))=BLACK;
color(w)=RED;
rrotate(w);
w=Right(P(x));
}
else
{
color(w)=Color(P(x));
color(P(x))=BLACK;
lrotate(P(x));
x=root;
}
}
else
{
pNode w=Left(P(x));
//case1
if(Color(w)==RED)
{
color(P(x))=RED;
rrotate(P(x));
w=Left(P(x));
}
//case 2,3,4
if(Color(Left(w))==BLACK && Color(Right(w)) ==BLACK)
{
color(w)=RED;
x=P(x);
}
else if(Color(Left(w)) == BLACK)
{
color(Right(w))=BLACK;
color(w)=RED;
lrotate(w);
w=Left(P(x));
}
else
{
color(w)=Color(P(x));
color(P(x))=BLACK;
rrotate(P(x));
x=root;
}
}
}
color(x)=BLACK;
}
/
//ά»¤size
void rbDeleteMaitainSize(pNode x)
{
cur=P(x);
while(cur!=nil)
{
size(cur)--;
cur=P(cur);
}
}
int Rank(pNode x)
{
int r= Size(Left(x))+1;
pNode y=x;
while(y!=root)
{
if( y == Right( P(y) ) )
{
r=r+Size(Left( P(y) ) )+1;
}
y=P(y);
}
return r;
}
pNode OS_Select(pNode x,int i)
{
if(i>Size(x))
return nil;
int r=Size(Left(x))+1;
if(i==r)
return x;
else if(i
return OS_Select(Left(x),i);
else
return OS_Select(Right(x),i-r);
}
friend class CMyWnd;//ÏÔʾºìºÚÊ÷µÄͼÐνçÃæÀࣻ
};
#endif