`

(转帖)红黑树算法

    博客分类:
  • java
阅读更多
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<E extends Comparable<E>> extends DefaultBSTree<E> implements BSTree<E> {

    
    
    public static class RBPrinter<E 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<E 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;
    }

}

 

 

链接地址:http://www.blogjava.net/javacap/archive/2010/07/25/169120.html#327076 

分享到:
评论

相关推荐

    论坛转帖工具.rar

    标题中的“论坛转帖工具.rar”表明这是一个用于在论坛之间转移帖子的软件工具,通常用于帮助用户方便地将一个论坛的帖子内容复制到另一个论坛,可能是为了分享信息、讨论或保存重要的帖子。这类工具可能包括自动抓取...

    [转帖]世界编程大赛第一名写的程序

    高效的数据结构如堆、树、图,以及高级算法如动态规划、贪心算法、回溯法等,都是赢得比赛的关键。例如,在处理大量数据时,哈希表可以提供快速的查找速度;而在解决最短路径问题时,Dijkstra算法或Floyd-Warshall算...

    UBB论坛转帖圣手.exe

    UBB论坛转帖圣手.exeUBB论坛转帖圣手.exe

    编辑人员转帖去水印工具

    总之,编辑人员转帖去水印工具如Teorex Inpaint,为图像编辑提供了便利,通过其独特的算法和技术,我们可以高效地去除图片中的水印,提高内容的质量。但在使用过程中,务必遵守版权法和相关法律法规,以维护良好的...

    贴吧转帖工具

    【贴吧转帖工具】是一种专为百度贴吧用户设计的便捷工具,主要用于提高用户在贴吧中的互动效率。通过这款工具,用户可以实现一键转帖和一键8经验签到的功能,极大地简化了传统操作流程,节省了用户的时间,提升了...

    discuz X2转帖工具、采集工具

    X2转帖工具、采集工具”是针对这个平台设计的辅助软件,主要用于帮助论坛管理员或用户批量发布帖子和采集内容,提高论坛内容更新的效率。 一、批量发帖功能 1. 自动化发布:此工具可以自动化地创建和发布帖子,...

    转帖别人的图片比较源码

    实现了从文件中导入位图、屏幕截图、鼠标指针截图、在图片上查找子图、在图片上查找颜色等功能。在查找过程中可以设定颜色变化范围、可以从左到右从上到下查找、也可以从指定点向四周查找,版权 2009,由 yeye55 ...

    转帖经典---JAVA设计模式

    《转帖经典---JAVA设计模式》这本书或资料可能涵盖了这些模式的详细解释、示例代码以及如何在实际项目中应用这些模式。通过学习和理解这些设计模式,开发者能够更好地设计和重构软件,提升代码质量。

    转帖工具ConvertX fordiscuz7.1/7.2 修改增强版.rar

    1.修改自Convert X转帖工具 2.新增批量替换关键词(原来是单个词语替换,可以利用这个功能删除一些网站的防转帖代码) 3.批量随机新增文字(新增内容可自定义,从而实现伪原创) 4.cookie记录替换和新增关键词(避免每次...

    转帖工具插件 for PHPwind 7.5 正式版.rar

    "转帖工具插件 for PHPwind 7.5 正式版" 是专门为 PHPwind 7.5 版本设计的一个功能插件,旨在提供便捷的帖子转移功能,帮助管理员或者用户将内容从一个地方轻松移动到另一个地方,而无需直接编辑论坛的原始文件。...

    一键转帖功能插件 for 帝国CMS 6.0 GBK utf8 V1.0.rar

    《一键转帖功能插件 for 帝国CMS 6.0 GBK utf8 V1.0》 本文将深入探讨“一键转帖功能插件”在帝国CMS 6.0系统中的应用与实现,该插件适用于GBK及UTF-8编码环境,旨在提升网站内容的分享与传播效率。我们将从安装...

    转帖图片提取工具 v1.0.zip

    转帖图片提取工具可以对论坛图片附件信息进行清除,只保留图片代码,操作很简单,推荐有需要转帖图片工具的朋友下载 转帖图片提取工具使用方法: 将IP138上处理过的东西复制到上方的编辑框内,点击只要图片,下面...

    Html2UBBMaxcj_Softii论坛专用转帖工具

    HTML2UBBMaxcj 是一款专为Softii论坛设计的转帖工具,它主要用于将HTML格式的帖子内容转换成UBB代码,以便在论坛中更好地显示和分享。UBB(Universal BBCode)是一种轻量级的标记语言,常用于网络论坛,与HTML类似,...

    一键转帖功能插件 for 帝国CMS v1.0.rar

    "一键转帖功能插件 for 帝国CMS v1.0.rar" 是一个专为帝国CMS设计的扩展工具,其主要目标是简化用户在网站上分享内容的过程,提高用户体验。这个插件允许用户轻松地将网站上的文章或信息复制并转发到其他平台,如...

    [转帖] 用C# Generator解决Hanoi塔问题

    通常,这样的文件会列出每一步盘子的移动情况,如“从柱A移动到柱B”,帮助用户直观地理解算法的执行过程。 综合以上信息,我们可以深入探讨以下几个知识点: 1. **汉诺塔问题**:这是一个典型的递归问题,可以...

    超级无敌转帖手

    看到论坛里帖子由精美的图片想转过来,或者批量提取地址时很好用

    高三政治教学总结(转帖)教学工作总结.doc

    高三政治教学总结(转帖)教学工作总结.doc

    (转帖)4x4x4立体led显示程序

    8. **图形算法**:如果要显示复杂的图像,可能需要应用基本的图形算法,如扫描线算法或深度排序,来决定LED的点亮顺序。 9. **调试与测试**:在实际开发过程中,对代码进行调试和测试至关重要,可能需要使用串口...

    J2ME全方位开发讲解基础汇总[转帖]

    J2ME全方位开发讲解基础汇总[转帖] 一、J2ME中需要的Java基础知识 现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成...

Global site tag (gtag.js) - Google Analytics