xiaopei的博客

--好好学习,天天向上

陈培军 ID:hxxiaopei
18147次访问,排名5990(-5)好友0人,关注者0
hxxiaopei的文章
原创 44 篇
翻译 0 篇
转载 7 篇
评论 6 篇
xiaopei的公告
-今年是菜鸟,明年成大牛- It is about Computer Science Technology
最近评论
vvukqr:wow power leveling
vvukqr:wow power leveling
lijing00333:很牛嘛
wenjie:baidu下yum源设置,没想到baidu到师兄你这了 挖哈哈~
xiaopei:所需要的头文件 sstream
文章分类
收藏
    相册
    兄弟
    Dave chen
    InterMa
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 红黑树(RBTree)的分析和实现收藏

    新一篇: 程序员应该学C语言的十个理由

    二叉排序树在查找方面提供了很大的方便,但是对worst-case查找/插入/删除/求最值 得时间复杂度都为O(n).

    红黑树可以保证在worst-case下查找/插入/删除等的复杂度得到O(lgN)。红黑树保持如下特性:

    1。节点不是red 就是black

    2。root为black

    3。所有的leaf为black

    4。所有red node 的孩子为black

    5。任一node通过左子树和右子树到达叶子节点的black node个数相同

    可以证明 红黑树的最大高度为2lg(N+1),所以在红黑树上的操作的时间复杂度为O(lgN)。 其插入和删除操作的时间复杂度都是O(lgN),插入最多需要2次旋转,删除最多需要3次旋转。

    其插入和删除操作可能会与红黑树的特性相违背,所以需要修正。在具体的实现中 1)插入的节点都是red。如果其父节点为red,就违背了条件4  2)如果删除的节点为black,违背了条件5需要修正。3)需要一个NIL来表示叶子节点,共享该叶子节点,且为root的父节点,节省空间。

    提供了查找 插入 删除 后继 最值操作。

    具体实现:

    //implement red-black tree
    /*
    *xiaopei
    *06/11/24
    */
    #ifndef RBTREE_H
    #define RBTREE_H
    template <typename Type>
    struct TreeNode
    {
      Type key;
      int color; 
      TreeNode *parent,*left,*right;
    };
    template <typename Type>
    class RBTree
    {
    private:
     enum
     {
      RED,BLACK
     }Color;
     Type key;
     int color; 
     TreeNode<Type> *parent,*left,*right;
     TreeNode<Type> *NIL;//
     TreeNode<Type> *ROOT;
     void left_rotate(TreeNode<Type> *&rotate);
     void right_rotate(TreeNode<Type> *&rotate);
     void RB_insert_fixup(TreeNode<Type>* &node);
     void RB_delete_fixup(TreeNode<Type>* &node);
    public:
     //const static TreeNode<Type>* nil;
     RBTree();
     TreeNode<Type> *successor(const TreeNode<Type> *node);
     TreeNode<Type>* insert(Type key);
     TreeNode<Type>* search(Type key);
     TreeNode<Type>* remove(Type key);
     TreeNode<Type> *maxnum(TreeNode<Type>*node);
     TreeNode<Type>* minnum(TreeNode<Type>*node);
     TreeNode<Type>* getRoot();
     void inorder(TreeNode<Type>*node);
     void test()
     {
      this->insert(1);
      this->insert(2);
      left_rotate(ROOT);
     }
     ~RBTree();
    };
    //template <typename Type>
    //const  TreeNode<Type>* RBTree<Type>::nil=NIL;
    template <typename Type>
    RBTree<Type>::RBTree()
    {
     NIL=new TreeNode<Type>;
     NIL->color=BLACK;
     NIL->key=123456;
     NIL->left=0;
     NIL->right=0;
     NIL->parent=0;
     ROOT=NIL;
    }
    template<typename Type>
    RBTree<Type>::~RBTree()
    {
     delete NIL;
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::maxnum(TreeNode<Type>*node)
    {
     //如果是空树怎么办?
     TreeNode<Type> *max=node;
     while(max->right!=NIL)
      max=max->right;
     return max;
    }
    template<typename Type>
    TreeNode<Type>*  RBTree<Type>::minnum(TreeNode<Type>*node)
    {
     //如果是空树怎么办?
     TreeNode<Type> *min=node;
      while(min->left!=NIL)
       min=min->left;
     return min;
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::successor(const TreeNode<Type>* node)
    {

     if(node->right!=NIL)
      return minnum(node->right);
      const TreeNode<Type>*s=node;
      const TreeNode<Type>*p=s->parent;
      while(p!=NIL&&s==p->right){s=p;p=s->parent;}
     return const_cast<TreeNode<Type>*>(p);
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::getRoot()
    {
     TreeNode<Type>*root=ROOT;
     return root;
    }
    template<typename Type>
    void  RBTree<Type>::left_rotate(TreeNode<Type>*& _rotate)
    {
     if(_rotate->right==NIL){cout<<"没有右孩子,不能左旋";return ;}//right child is nil, so can not left rotate

     TreeNode<Type>* r = _rotate->right;
     TreeNode<Type>*t,*rotate=_rotate;
     //deal with r->left
     rotate->right=r->left;
     r->left->parent=rotate;
     
     //deal with r
    // t=rotate->parent;
     // r->parent=t;//rotate 被修改成了NIL 为什么?
    // rotate=rotate->parent;
     if(rotate->parent==NIL)
     {ROOT=r;r->parent=NIL;}
     else if(rotate==rotate->parent->left)
      rotate->parent->left=r;
     else
      rotate->parent->right=r;
     r->parent=rotate->parent;
     //deal with rotate
     rotate->parent=r;
     r->left=rotate;
    }
    template<typename Type>
    void  RBTree<Type>::right_rotate(TreeNode<Type>* &_rotate)
    {
     TreeNode<Type>*rotate=_rotate;//不知道为什么,如果直接对_rotate操作,在过程中会改变_rotate得值
     if(rotate->left==NIL)return ;//left child is NIL, so can not right rotate
     TreeNode<Type>* l = rotate->left;
     //deal with l->right
     //cout<<"key"<<rotate->parent->key<<endl;
     l->right->parent=rotate;
     rotate->left=l->right;
     //deal with l
     l->parent=rotate->parent;
     if(rotate->parent==NIL)
     {ROOT=l;l->parent=NIL;}
     else if(rotate==rotate->parent->left)
      rotate->parent->left=l;
     else
      rotate->parent->right=l;
     //deal with rotate
     rotate->parent=l;
     l->right=rotate;
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::insert(Type key)
    {
     TreeNode<Type> *node=new TreeNode<Type>;

     TreeNode<Type> *down=ROOT;
     TreeNode<Type> *s=NIL;
     while(down!=NIL)
     {
      s=down;
      if(key<down->key)
       down=down->left;
      else
       down=down->right;
     }//找到合适位置
     node->parent=s;
     if(s==NIL)
     {ROOT=node;node->parent=NIL;}
     else if(key<s->key)
      s->left=node;
     else
      s->right=node;
     node->key=key;
     node->left=NIL;
     node->right=NIL;
     node->color=RED;

     RB_insert_fixup(node);
     return node;
    }
    template<typename Type>
    void RBTree<Type>::RB_insert_fixup(TreeNode<Type>*& change)
    {
    // TreeNode<Type>*change=node;
     TreeNode<Type>*father;
      TreeNode<Type>*uncle;
     while(change->parent->color==RED)
     {
      father=change->parent;
      if(father==father->parent->left)
      {
       uncle=father->parent->right;//父节点的兄弟
       if(uncle->color==RED)//uncle同样为red
       {
        father->color=BLACK;
        uncle->color=BLACK;
        father->parent->color=RED;
        change=father->parent;//进行循环
       }else
       {
        //cout<<"uncle node color=black"<<endl;
        if(change==father->right)//内插入,左旋
        {
         change=father;
         //cout<<"before rotate key:"<<change->key<<" color "<<change->color<<endl;
         left_rotate(change);
         father=change->parent;
         //cout<<"after rotate key:"<<change->key<<" color "<<change->color<<endl;
        // cout<<"内插入"<<endl;
        }
        //外插入
        father->color=BLACK;
        father->parent->color=RED;//改变颜色
       // cout<<"before rotate key:"<<change->key<<" color "<<change->color<<endl;
        right_rotate(father->parent);
       // cout<<"before rotate key:"<<change->key<<" color "<<change->color<<endl;
       }
      }
      else
      {
       uncle=father->parent->left;//父节点的兄弟
       if(uncle->color==RED)//uncle同样为red
       {
        father->color=BLACK;
        uncle->color=BLACK;
        father->parent->color=RED;
        change=father->parent;//进行循环
       }else
       {
        if(change==father->left)//内插入
        {
         change=father;
         right_rotate(change);
         father=change->parent;
        }
        //外插入
        father->color=BLACK;
        father->parent->color=RED;
        left_rotate(father->parent);
       }
      }
     }
     ROOT->color=BLACK;
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::search(Type key)
    {
     TreeNode<Type> *p=ROOT;
     while(p!=NIL&&p->key!=key)
     {
      if(key<p->key)
       p=p->left;
      else
       p=p->right;
     }
     return p;
    }
    template<typename Type>
    TreeNode<Type>* RBTree<Type>::remove(Type key)
    {
     TreeNode<Type> *p = this->search(key);
     if(p==NIL)
      return p;
     //rn 为需要改变的节点,找到得key节点,如果只有一个孩子或者没有孩子,则需要被删除的就是该节点,否则(两个孩子)
     //需要删除的是直接后继节点(首先将key节点用后继节点代替)后继节点没有左孩子
     //最后rn最多只有一个孩子
     TreeNode<Type> *rn=NIL;
     TreeNode<Type> *act;
     if(p->left==NIL || p->right==NIL)
      rn=p;
     else
      rn = this->successor(p);
     if(rn->left!=NIL)//如果被删除的节点左孩子不空,则使用act纪录(key节点只有左孩子的情况)
      act=rn->left;
     else//act纪录key没有孩子,有右孩子,双子情况
      act=rn->right;
     
     act->parent=rn->parent;//更新父节点
     if(rn->parent==NIL)
      ROOT=act;//已经将act得parent修改成NIL了
     else if(rn == rn->parent->left)
      rn->parent->left=act;
     else
      rn->parent->right=act;
     if(rn!=p)//key有两个孩子时,实际删除的是p的直接后继rn节点,所以需要将后继节点的信息复制key节点中
      p->key=rn->key;
     if(rn->color==BLACK)
      RB_delete_fixup(act);
     return rn;
    }
    //删除一个黑色节点后导致两边的bh不同。
    template<typename Type>
    void RBTree<Type>::RB_delete_fixup(TreeNode<Type> *&_node)
    {

     TreeNode<Type>*father,*brother,*node;
     node=_node;
     father=node->parent;
     while(node!=ROOT&&node->color==BLACK)//如果color(x)为red,只需要讲color(x)=black就行了
     {
      if(node=father->left)//color(node)=black,father左孩子得black nodes(m-1) =father右孩子的black nodes(m) -1
      {
       brother=father->right;
       if(brother->color==RED)//color(father)=black,********************case 1
       {
        brother->color=BLACK;
        father->color=RED;
        left_rotate(father);//修改了树结构,这一步后brother为node得祖父节点并且brother右孩子的black nodes = m不变
        brother=parent->right;//修正node得兄弟节点,现在color(father)=black right(father)=black,并且father->left得
        //black nodes还为m-1,father->right得black nodes = m
       }

       //如果兄弟为黑,则根据兄弟的孩子来区分,color(Node)=black,color(brother)=black,color(father)未知

       if(brother->left->color==BLACK&&brother->right->color==BLACK)//********************case 2
       {
        brother->color=RED;//fater右孩子的black nodes = m-1
        node=father;//如果father为red,则循环结束,将father改为black,则整个以father为根的子树左右孩子的black nodes都为m
       }
       else
       {
        if(brother->right->color==BLACK)//右孩子为黑色********************case 3
        {
         brother->left->color=BLACK;
         brother->color=RED;
         right_rotate(brother);     
         brother=father->right;//brother的右孩子为red
        }
        //if(brother->right->color==RED)************************case 4
        father->color=BLACK;
        brother->right->color=BLACK;//red修改成black
        brother->color=father->color;
        //执行旋转后,brother为node得祖父,brother右孩子得black nodes=m,做孩子的black nodes=m(+father为黑色)
        left_rotate(father);
        node=ROOT;//结束
       }
      }
     }
     node->color=BLACK;
    }
    template<typename Type>
    void RBTree<Type>::inorder(TreeNode<Type>*node)
    {
     if(node!=NIL)
     {
      inorder(node->left);
      if(node->color==RED)
       if(node->left->color==RED||node->right->color==RED)
        cout<<"wrong"<<" ";
      cout<<node->key<<" ";
      inorder(node->right);
     }
     
    }
    #endif

     

    发表于 @ 2006年11月25日 16:53:00|评论(loading...)|编辑

    旧一篇: 数据结构:最小堆/哈希表/二叉树/平衡二叉树/红黑树的意义(什么情况下使用)

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © xiaopei