E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
          紅黑樹可能是要考慮情況最多的BST樹了,它有自己的規則(見代碼的注釋),通過這些規則可以保證花費較小的代價來達到相對平衡。
          注意,紅黑樹仍然不是平衡樹,但是統計性能要好于AVL樹。
          要保持紅黑樹的規則,主要通過兩類操作,一類是換色,一類還是旋轉。
          紅黑樹插入主要要解決紅-紅沖突,而刪除主要則解決“雙黑”

          同樣,紅黑樹的刪除節點實現是最復雜的,不過,復雜也就在于考慮的情況多,掌握了這幾種情況實現還是不困難。
          其實,紅黑樹其實是一顆擴充的二叉樹,所以也是滿二叉樹,其空節點可以看做是擴充的葉節點。但是紅黑樹的擴充葉節點是有特殊意義的。


          下面是代碼:

          package algorithms.tree;

          /**
           * R-B Tree has following four rules:
           * 1)every node is either red or black
           * 2)root and empty node (external leaf node) are always black.
           * 3)the red node's parent node must be black
           * 4)every simple path start from node X to its descendant contains same number of black node
           * 
           * 
           * 
          @author yovn
           *
           
          */
          public class RBTree<extends Comparable<E>> extends DefaultBSTree<E> implements BSTree<E> {

              
              
              
          public static class RBPrinter<extends Comparable<E>> implements DefaultBSTree.NodeVisitor<E>
              {

                  @Override
                  
          public void visit(E ele) {
                      
                      
                  }

                  @Override
                  
          public void visitNode(algorithms.tree.DefaultBSTree.BSTNode<E> node) {
                      RBNode
          <E> n=(RBNode<E>)node;
                      
          if(!n.isNull())
                      System.out.print(n.key
          +"("+(n.color==RBNode.RED?"RED":"BLACK")+"),");
                      
                  }
                  
              }
              
          static class RBNode<extends Comparable<E>> extends BSTNode<E>
              {



                  
          static final boolean RED=false;
                  
          static final boolean BLACK=true;
                  
                  
                  
                  RBNode
          <E> parent;
                  
          boolean color;//red or black
                  
                  
                  RBNode(RBNode
          <E> p,E key,boolean color) {
                      
          super(key);
                      
          this.color=color;
                      
          this.parent=p;
                      
                  }
                  
                  
                  
                  
          final boolean isNull(){return key==null;}
                  
              }
              
              
                  
              @Override
              
          public final boolean delete(E ele) {
                  RBNode
          <E> cur;
                  
                  
          int cmp;
                  
          if(root==null)return false;
                  cur
          =(RBNode<E>)root;
                  
          while(!cur.isNull()&&(cmp=ele.compareTo(cur.key))!=0)
                  {
                      
          if(cmp<0)cur=(RBNode<E>)cur.left;
                      
          else cur=(RBNode<E>)cur.right;
                          
                  }
                  
          if(cur.isNull())
                  {
                      
          //can't find specified key
                      return false;
                  }
                  
          if(!((RBNode<E>)cur.left).isNull()&&!((RBNode<E>)cur.right).isNull())
                  {
                      RBNode
          <E> prev=(RBNode<E>)cur.left;
                  
                      
          while(!((RBNode<E>)prev.right).isNull())
                      {
                          
                          prev
          =(RBNode<E>)prev.right;
                      }
                      cur.key
          =prev.key;
                      cur
          =prev;
                  
                  }
                  
          if(!((RBNode<E>)cur.left).isNull())
                  {
                      
          if (cur == root) {
                          root 
          = cur.left;
                          ((RBNode
          <E>)root).color=RBNode.BLACK;
                          
          return true;
                      }
                      
                      
          if(cur.parent.left==cur)
                      {
                          cur.parent.left
          =cur.left;
                          ((RBNode
          <E>)cur.left).parent=cur.parent;
                      }
                      
          else
                      {
                          cur.parent.right
          =cur.left;
                          ((RBNode
          <E>)cur.left).parent=cur.parent;
                      }
                      
          if(cur.color==RBNode.BLACK)
                      {
                          ((RBNode
          <E>)cur.left).color=RBNode.BLACK;
                      }
                  }
                  
          else if(!((RBNode<E>)cur.right).isNull())
                  {
                      
          if (cur == root) {
                          root 
          = cur.right;
                          ((RBNode
          <E>)root).color=RBNode.BLACK;
                          
          return true;
                      }
                      
                      
          if(cur.parent.left==cur)
                      {
                          cur.parent.left
          =cur.right;
                          ((RBNode
          <E>)cur.right).parent=cur.parent;
                      }
                      
          else
                      {
                          cur.parent.right
          =cur.right;
                          ((RBNode
          <E>)cur.right).parent=cur.parent;
                      }
                      
          if(cur.color==RBNode.BLACK)
                      {
                          ((RBNode
          <E>)cur.right).color=RBNode.BLACK;
                      }
                  }
                  
          else
                  {
                      
          if(cur==root)
                      {
                          root
          =null;
                          
          return true;
                      }
                      RBNode
          <E> todo;
                      
          if(cur.parent.left==cur)
                      {
                          todo
          =newNullNode(cur.parent);
                          cur.parent.left
          =todo;
                      }
                      
                      
          else
                      {
                          todo
          =newNullNode(cur.parent);
                          cur.parent.right
          =todo;
                      }
                      
          if(cur.color==RBNode.BLACK)
                      {
                          
          //now todo is a double black node, we will eliminate the double black
                          fixup_double_black(todo);
                      }
                      
                  }
                  
                  
          return true;
              }

              @Override
              
          public E findMax() {
                  
          if(isEmpty())return null;
                  BSTNode
          <E> node=root;
                  
          while(!((RBNode<E>)node.right).isNull())
                  {
                      node
          =node.right;
                  }
                  
          return node.key;
              }


              @Override
              
          public E findMin() {
                  
          if(isEmpty())return null;
                  BSTNode
          <E> node=root;
                  
          while(!((RBNode<E>)node.left).isNull())
                  {
                      node
          =node.left;
                  }
                  
          return node.key;
              }

              
          private final RBNode<E> newNullNode(RBNode<E> p)
              {
                  
          return new RBNode<E>(p,null,RBNode.BLACK);
              }
              
              
          private final RBNode<E> newNormalNode(RBNode<E> p,E key, boolean color)
              {
                  RBNode
          <E> node= new RBNode<E>(p,key,color);
                  node.left
          =newNullNode(node);
                  node.right
          =newNullNode(node);
                  
          return node;
              }

              
          private final void fixup_double_black(RBNode<E> cur) {
                  
                  RBNode
          <E> sibling;
                  RBNode
          <E> p;
              
                  
          while(cur!=root)//until its parent,parent maybe double black 
                  {
                      p
          =cur.parent;
                      
          if(p.left==cur)
                      {
                          sibling
          =(RBNode<E>)p.right;
                          
          if(sibling.color==RBNode.RED)
                          {
                              rotate_from_right(p);
                              p.color
          =RBNode.RED;
                              sibling.color
          =RBNode.BLACK;//actually, p.parent==sibling, remember we have done one rotation
                              
          //this case  transformed to another case handled in other place
                          }
                          
          else 
                          {
                              
          if(((RBNode<E>)sibling.right).color==RBNode.RED)
                              {
                                  rotate_from_right(p);
                                  sibling.color
          =p.color;//also, p.parent==sibling, some textbook say here sibling's color can be red while not violate the 3th rule, i don't think so.
                                  p.color=RBNode.BLACK;
                                  ((RBNode
          <E>)sibling.right).color=RBNode.BLACK;
                                  
          //ok done!
                                  return;
                                  
                              }
                              
          else if(((RBNode<E>)sibling.left).color==RBNode.RED)
                              {
                                  rotate_from_left(sibling);
                                  sibling.color
          =RBNode.RED;
                                  sibling.parent.color
          =RBNode.BLACK;//its parent was previously be its left child, remember we have done a left rotation from sibling
                                  
                                  
          // now transformed to previous case, double black 's sibling(black) have right child colored red
                                  
                              }
                              
          else //  sibling's two children are both black
                              {
                                  
          //re-coloring the sibling and parent
                                  sibling.color=RBNode.RED;
                                  
          if(p.color==RBNode.BLACK)
                                  {
                                      cur
          =p;
                                      
          //now the cur node was not double black node ,but p was a double black
                                  }
                                  
          else
                                  {
                                      p.color
          =RBNode.BLACK;//eliminated the double black node 
                                      return;
                                  }
                              }
                          }
                      }
                      
          else
                      {
                          sibling
          =(RBNode<E>)p.left;
                          
          if(sibling.color==RBNode.RED)
                          {
                              rotate_from_left(p);
                              p.color
          =RBNode.RED;
                              sibling.color
          =RBNode.BLACK;//actually, p.parent==sibling, remember we have done one rotation
                              
          //this case  transformed to another case handled in other place
                          }
                          
          else 
                          {
                              
          if(((RBNode<E>)sibling.left).color==RBNode.RED)
                              {
                                  rotate_from_left(p);
                                  sibling.color
          =p.color;//also, p.parent==sibling, some textbook say here sibling's color can be red while not violate the 3th rule, i don't think so.
                                  p.color=RBNode.BLACK;
                                  ((RBNode
          <E>)sibling.left).color=RBNode.BLACK;
                                  
          //ok done!
                                  return;
                                  
                              }
                              
          else if(((RBNode<E>)sibling.right).color==RBNode.RED)
                              {
                                  rotate_from_right(sibling);
                                  sibling.color
          =RBNode.RED;
                                  sibling.parent.color
          =RBNode.BLACK;//its parent was previously be its right child, remember we have done a left rotation from sibling
                              
                                  
          // now transformed to previous case, double black 's sibling(black) have right child colored red
                                  
                              }
                              
          else //  sibling's two children are both black
                              {
                                  
          //re-coloring the sibling and parent
                                  sibling.color=RBNode.RED;
                                  
          if(p.color==RBNode.BLACK)
                                  {
                                      cur
          =p;
                                      
          //now the cur node was not double black node ,but p was a double black
                                  }
                                  
          else
                                  {
                                      p.color
          =RBNode.BLACK;//eliminated the double black node 
                                      return;
                                  }
                              }
                          }
                      }
                  }
                  
              }

              



              @Override
              
          public final void insert(E ele) {
                  
          if(root==null)
                  {
                      root
          =newNormalNode(null,ele,RBNode.BLACK);//now root's black-height(bh) is 1
                      return;
                  }
                  RBNode
          <E> ret=_insert((RBNode<E>)root,ele);//first insert it
                  _insert_fixup(ret);//fix-up the R-B tree from node cur;
              }
              
              
              
          private final void _insert_fixup(RBNode<E> cur) {
                  
                  RBNode
          <E> p,g;
              
                  
          //we should fix until it is black colored
                  while(cur!=root&&cur.color==RBNode.RED)
                  {
                      p
          =cur.parent;
                      
          if(p.color==RBNode.BLACK)
                      {
                          
          //that's fine, the insertion will not change any black height, and will not violate any rule.
                          return;
                      }
                      g
          =p.parent;//we can assume the p is not null now.
                      
                      
          if(p==g.left)
                      {
                          RBNode
          <E> uncle=(RBNode<E> )g.right;
                          
          if(uncle.color==RBNode.RED)
                          {
                              
          //re-coloring
                              g.color=RBNode.RED;
                              uncle.color
          =p.color=RBNode.BLACK;
                              
                              
          //now the g maybe conflict with its parent;
                              cur=g;
                          }
                          
          else
                          {
                              
          if(cur==p.right)
                              {
                                  
          //this case we should do left rotation, and then it will transform to next case
                                  cur=rotate_from_right(p);
                                  cur
          =(RBNode<E>)cur.left;
                                  
          //transformed to next case    
                              }
                              
                              cur
          =rotate_from_left(g);
                              cur.color
          =RBNode.BLACK;
                              ((RBNode
          <E>)cur.left).color=((RBNode<E>)cur.right).color=RBNode.RED;
                                              
                          
                          }
                          
                      }
                      
          else
                      {
                          RBNode
          <E> uncle=(RBNode<E> )g.left;
                          
          if(uncle.color==RBNode.RED)
                          {
                              
          //re-coloring
                              g.color=RBNode.RED;
                              uncle.color
          =p.color=RBNode.BLACK;
                              
                              
          //now the g maybe conflict with its parent;
                              cur=g;
                          }
                          
          else
                          {
                              
          if(cur==p.left)
                              {
                                  
          //this case we should do right rotation, and then it will transform to next case
                                  cur=rotate_from_left(p);
                                  cur
          =(RBNode<E>)cur.right;
                                  
          //transformed to next case    
                              }
                              
                              cur
          =rotate_from_right(g);
                              cur.color
          =RBNode.BLACK;
                              ((RBNode
          <E>)cur.left).color=((RBNode<E>)cur.right).color=RBNode.RED;
                                              
                          
                          }
                      }
                          
                  }
                  ((RBNode
          <E>)root).color=RBNode.BLACK;
                  
                  
              }




              
          private final RBNode<E> rotate_from_right(RBNode<E> p) {
                  
                  RBNode
          <E> g=p.parent;
                  RBNode
          <E> cur=(RBNode<E>)p.right;
                  
                  p.right
          =cur.left;
                  
          if(cur.left!=null)((RBNode<E>)cur.left).parent=p;
                  
                  cur.left
          =p;
                  p.parent
          =cur;
                  
                  
                  
          if(g!=null)
                  {
                      
          if(g.left==p)g.left=cur;
                      
          else g.right=cur;
                  }
                  
          else root=cur;
                  
                  cur.parent
          =g;
                  
          return cur;
                  
              
              }




              
          private final RBNode<E> rotate_from_left(RBNode<E> p) {
                  RBNode
          <E> g=p.parent;
                  RBNode
          <E> cur=(RBNode<E>)p.left;
                  
                  p.left
          =cur.right;
                  
          if(cur.right!=null)((RBNode<E>)cur.right).parent=p;
                  
                  cur.right
          =p;
                  p.parent
          =cur;
                  
                  
                  
          if(g!=null)
                  {
                      
          if(g.left==p)g.left=cur;
                      
          else g.right=cur;
                  }
                  
          else root=cur;
                  
                  cur.parent
          =g;
                  
          return cur;
              }




              
          private final RBNode<E> _insert(RBNode<E> cur,E ele)
              {
                  
                  RBNode
          <E> parent=null;
                  
          int cmp;
                  
          boolean left=false;
                  
          while(!cur.isNull()&&(cmp=ele.compareTo(cur.key))!=0)
                  {
                      parent
          =cur;
                      
          if(cmp<0)
                      {
                          cur
          =(RBNode<E>)cur.left;
                          left
          =true;
                          
                      }
                      
          else {cur=(RBNode<E>)cur.right;left=false;}
                      
                  }
                  
          if(!cur.isNull())throw new IllegalArgumentException("can't insert duplicate key!");
                  cur
          =newNormalNode(parent,ele,RBNode.RED);
                  
          if(left)parent.left=cur;
                  
          else parent.right=cur;
                  
          return cur;
              }




              
          /**
               * 
               
          */
              
          public RBTree() {
                      root
          =null;
              }

          }





          posted on 2007-12-20 18:25 DoubleH 閱讀(8506) 評論(20)  編輯  收藏

          Feedback

          # re: 紅黑樹的Java實現 2007-12-23 22:43 bwl
          似乎是老外寫的。。。。。。。。  回復  更多評論
            

          # re: 紅黑樹的Java實現 2007-12-24 12:26 Javacap
          @bwl
          不好意思,我通常寫代碼都喜歡英文注釋,很少寫中文注釋,要么就干脆不注釋,老感覺寫代碼加上中文注釋挺別扭的,代碼哪怕一個字也沒有參看別人的。  回復  更多評論
            

          # re: 紅黑樹的Java實現 2007-12-24 14:47 過路
          Java功底不錯。
            回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2008-02-14 18:20 wangj
          可能你使用的Java的IDE對中文支持不好,良好的代碼是要盡量給別人看的,只要有基礎的人看不懂,特別加了注釋還不如不加的話,那最好不加。
          其實很多JSP和J2ME程序都要使用中文的,因為畢竟面對的是中文界面用戶,從理論上來說數據結構是不需要中文的,但是數據結構一般都是用C或者Delphi編的,然后通過JNI調用的,因此用Java就是用對象,你可惜做的并不好  回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2008-02-14 18:24 wangj
          @Javacap
          你的程序還不是老外寫的,如果向老外看齊的話,請先把軟件書寫規范點。問題太多了,直說2點吧,第一等號兩邊都要空格,第二,多條語句必須寫多行
            回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2009-01-14 11:41 wangj
          @wangj
          2b真多  回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2009-01-14 16:59 wangj
          wangj = 2b
            回復  更多評論
            

          # re: 紅黑樹的Java實現 2009-07-28 15:35 satitan
          如果提不出實質性的意見,請像我一樣稱贊一下博主的OPEN精神:非常好,已閱  回復  更多評論
            

          # re: 紅黑樹的Java實現 2009-08-19 22:03 lixmin
          我喜歡, 已閱  回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2009-12-10 22:53 Daniel
          @wangj

          請那些不懂算法別在這里亂評論,正如有位仁兄所說“2B真多”
          樓主我很欣賞  回復  更多評論
            

          # re: 紅黑樹的Java實現 2009-12-19 22:21 tcelvis
          能不能把其他幾個相關類的代碼也給放出來?DefaultBSTree和BSTree等等,光看這個有些不明白。為什么RBnode中只定義parents而直接使用父類的left和right?據我所知BSTree的結點也應該有parents域才對。  回復  更多評論
            

          # re: 紅黑樹的Java實現 2009-12-19 23:51 tcelvis
          還有一個不太理解的地方。為什么你的每個子類都要定義一個<E extends Comparable<E>>?這實際上不是把RBTree定義的<E extends Comparable<E>>給隱藏了么?直接引用RBTree已經定義的E不可以么?  回復  更多評論
            

          # re: 紅黑樹的Java實現 2010-07-25 15:26 姚朝文
          別忘了,你現在寫的東西,都是給國人看的多!不是對自己的英語很自信就拿來炫,最好給出中英注釋!  回復  更多評論
            

          # re: 紅黑樹的Java實現 2010-11-24 12:42 big
          @姚朝文
          連英文都不看你還寫什么code, 回家洗洗睡吧, 人家欠你的嗎?還好意思要中英注釋, 莫名其妙。  回復  更多評論
            

          # re: 紅黑樹的Java實現 2011-01-05 21:51 stxpascal
          package algorithms.tree 這個包在哪啊?  回復  更多評論
            

          # re: 紅黑樹的Java實現 2011-03-04 11:16 chs
          你腦門被夾了吧,看不懂不要看,照你這么說你在中國,那你學英語干屁啊,都是21世紀的人,國家提倡學習英語,你還在這里給國人看。2B @姚朝文
            回復  更多評論
            

          # re: 紅黑樹的Java實現[未登錄] 2013-01-05 14:39 大大
          干你媽比的,要么寫中文注釋,要么死回你媽比里去,會倆英文,拽尼瑪腿啊  回復  更多評論
            

          # re: 紅黑樹的Java實現 2014-02-02 16:47 new
          刪除部分的代碼貌似不對啊。
          如果刪除的是一個左右子樹都存在的節點,那么成分會先找到前序節點,并把cur指向該節點(該節點沒有右子樹存在)。
          接下來進入判斷,如果cur存在左子樹,把左子樹賦給cur的父節點。
          問題在于被刪除節點的父節點和cur之間沒有了關聯(沒有設置)。
          而且對于某些額情況,還會存在左子樹作為了被刪除節點的子樹。例如,對于深度為2的滿二叉樹,對左1添加子節點之后,刪除根節點的左節點。

          請樓主再仔細驗證一下。  回復  更多評論
            

          # re: 紅黑樹的Java實現 2014-02-26 20:27 super fly
          想問一下,這個是完整,直接能用的代碼嗎???好像是不怎么行耶?  回復  更多評論
            

          # re: 紅黑樹的Java實現 2014-02-26 20:38 super fly
          怎么找到這個DefaultBSTree和BSTree啊?@new  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 静安区| 巴塘县| 旬邑县| 招远市| 彝良县| 桃源县| 连山| 微博| 恭城| 崇信县| 湛江市| 共和县| 武清区| 巩留县| 通道| 房产| 花莲市| 东城区| 连山| 同仁县| 濉溪县| 呼伦贝尔市| 忻州市| 同德县| 隆安县| 平乡县| 阳朔县| 三原县| 黎城县| 南江县| 盘锦市| 赤水市| 平陆县| 金华市| 岳普湖县| 湟中县| 临潭县| 汶川县| 米泉市| 昭通市| 天峻县|