算法研究--使用 红黑树 解决实际问题(理论与实践)

    在查找中,虽然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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值