前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >红黑树算法的Java实现

红黑树算法的Java实现

作者头像
csxiaoyao
发布2019-02-18 18:14:31
1.4K0
发布2019-02-18 18:14:31
举报
文章被收录于专栏:csxiaoyaocsxiaoyaocsxiaoyao

红黑树算法的Java实现

我的主页 www.csxiaoyao.com

红黑树

github: https://github.com/csxiaoyaojianxian/JavaAlgorithms


NodeColor.java

public class NodeColor {
    public static String Red = "red";
    public static String Black = "black";
}

RedBlackTreeNode.java

public class RedBlackTreeNode {
    private String color;
    private int key;
    private RedBlackTreeNode left;
    private RedBlackTreeNode right;
    private RedBlackTreeNode parent;
    //构造Nil结点
    public RedBlackTreeNode(){
        this.color = NodeColor.Black;
        this.key = 0;
        this.left = null;
        this.right = null;
        this.parent = null;
    }
    //构造结点
    public RedBlackTreeNode(String color, int key, RedBlackTreeNode left, RedBlackTreeNode right, RedBlackTreeNode parent){
        this.color = color;
        this.key = key;
        this.left = left;
        this.right = right;
        this.parent = parent;
    }
    //获取颜色
    public String getColor() {
        return color;
    }
    //设置颜色
    public void setColor(String color) {
        this.color = color;
    }
    //获取值
    public int getKey() {
        return key;
    }
    //设置值
    public void setKey(int key) {
        this.key = key;
    }
    //获取左子树
    public RedBlackTreeNode getLeft() {
        return left;
    }
    //设置左子树
    public void setLeft(RedBlackTreeNode left) {
        this.left = left;
    }
    //获取右子树
    public RedBlackTreeNode getRight() {
        return right;
    }
    //设置右子树
    public void setRight(RedBlackTreeNode right) {
        this.right = right;
    }
    //获取父结点
    public RedBlackTreeNode getParent() {
        return parent;
    }
    //设置父结点
    public void setParent(RedBlackTreeNode parent) {
        this.parent = parent;
    }
}

RedBlackTree.java

public class RedBlackTree {
    private static RedBlackTreeNode nil = new RedBlackTreeNode();
    private RedBlackTreeNode root = new RedBlackTreeNode();
    //构造空红黑树
    public RedBlackTree(){
        root = nil;
    }
    //创建结点
    public RedBlackTreeNode RB_NODE(int key){
        RedBlackTreeNode node = new RedBlackTreeNode(NodeColor.Red, key, nil, nil, nil);
        return node;
    }
    //判断是否为Nil结点
    public boolean IsNil(RedBlackTreeNode node){
        if( node == nil){
            return true;
        }else{
            return false;
        }       
    }
    //获取根结点
    public RedBlackTreeNode getRoot() {
        return root;
    }
    //设置根结点
    public void setRoot(RedBlackTreeNode root) {
        this.root = root;
    }
    //插入结点
    public void RB_INSERT(RedBlackTree T, RedBlackTreeNode z){
        //临时变量结点y,存储临时结点,默认为Nil
        RedBlackTreeNode y = T.nil;
        //x初试为根结点
        RedBlackTreeNode x = T.getRoot();
        //循环二查找合适的插入点
        while( IsNil(x) == false ){
            //保存当前结点,作为结果的根结点
            y = x;
            if( z.getKey() < x.getKey() ){
                //查找左子树
                x = x.getLeft();
            }else{
                //查找右子树
                x = x.getRight();
            }
        }
        //临时结点y设置为插入点的父结点
        z.setParent(y);

        if(  IsNil(y) == true ){
            //空树时设置z为根结点        
            T.setRoot(z);
        }else if( z.getKey() < y.getKey() ){
            //插入为左子树
            y.setLeft(z);
        }else{
            //插入为右子树
            y.setRight(z);
        }
        //将插入结点的左右子树设为Nil,颜色为红色,已经在构造时设置过,可以省略
        z.setLeft(T.nil);
        z.setRight(T.nil);
        z.setColor(NodeColor.Red);
        //插入调整
        RB_INSERT_FIXUP(T, z);
    }
    //插入调整
    public void RB_INSERT_FIXUP(RedBlackTree T, RedBlackTreeNode z){
        //当z的父结点为红色时,插入结点和父结点同为红色,需要调整
        while( z.getParent().getColor() == NodeColor.Red ){
            //插入结点的父结点是祖父节点的左子树
            if( z.getParent() == z.getParent().getParent().getLeft() ){
                //y定义为叔叔结点
                RedBlackTreeNode y = z.getParent().getParent().getRight();
                //case1:如果叔叔结点为红色,上层父结点和叔叔结点设为黑色,祖父节点设为红色
                if( y.getColor() == NodeColor.Red ){
                    z.getParent().setColor(NodeColor.Black);
                    y.setColor(NodeColor.Black);
                    z.getParent().getParent().setColor(NodeColor.Red);
                    //祖父结点设为z
                    z = z.getParent().getParent();
                }
                //case2:插入结点为父结点的右子树,(叔叔结点一定为黑色),父结点设为z,对z左旋
                else if( z == z.getParent().getRight() ){
                    //对父结点左旋
                    z = z.getParent();
                    LEFT_ROTATE(T, z);
                }
                //case3:插入结点为父结点的左子树,(叔叔结点一定为黑色),父结点设为黑色,祖父结点设为红色,对祖父结点右旋
                z.getParent().setColor(NodeColor.Black);
                z.getParent().getParent().setColor(NodeColor.Red);
                RIGHT_ROTATE(T, z.getParent().getParent());
            }
            //插入结点的父结点是祖父节点的右子树,同理,方向交换
            else{
                RedBlackTreeNode y = z.getParent().getParent().getLeft();
                if( y.getColor() == NodeColor.Red ){
                    z.getParent().setColor(NodeColor.Black);
                    y.setColor(NodeColor.Black);
                    z.getParent().getParent().setColor(NodeColor.Red);
                    z = z.getParent().getParent();
                }
                else if( z == z.getParent().getLeft() ){
                    z = z.getParent();
                    RIGHT_ROTATE(T, z);
                }
                z.getParent().setColor(NodeColor.Black);
                z.getParent().getParent().setColor(NodeColor.Red);
                LEFT_ROTATE(T, z.getParent().getParent());
            }
        }
        T.getRoot().setColor(NodeColor.Black);
    }
    //删除结点子函数,把根结点为u的子树替换为根结点为v的子树
    public void RB_TRANSPLANT( RedBlackTree T, RedBlackTreeNode u, RedBlackTreeNode v){
        //u为根结点
        if( IsNil(u.getParent()) ){
            T.root = v;
        }
        //u为左子树
        else if( u == u.getParent().getLeft() ){
            u.getParent().setLeft(v);
        }
        //u为右子树
        else{
            u.getParent().setRight(v);
        }
        //父结点交换
        v.setParent(u.getParent());
    }
    //查找后继
    public RedBlackTreeNode TREE_MINIMUM(RedBlackTreeNode x){
        //不断查找左子树
        while( IsNil(x.getLeft()) == false ){
            x = x.getLeft();
        }
        return x;
    }
    //删除结点
    public void RB_DELETE(RedBlackTree T, RedBlackTreeNode z){
        //临时结点y保存即将删除的结点z信息
        RedBlackTreeNode y = z;
        //在结点删除或者移动前必须保存结点的颜色
        String yOriginColor = y.getColor();
        //临时结点x,用于记录y的位置
        RedBlackTreeNode x = null;
        //case1:z无左子树,直接将右子树置于z位置
        if( IsNil(z.getLeft()) == true ){
            x = z.getRight();
            RB_TRANSPLANT(T, z, z.getRight());
        }
        //case2:z无右子树,直接将左子树置于z位置
        else if( IsNil(z.getRight()) == true ){
            x = z.getLeft();
            RB_TRANSPLANT(T, z, z.getLeft());
        }
        //case3:z有左右子树
        else{
            //找到右子树中最小的结点,即z的后继
            y = TREE_MINIMUM(z.getRight());
            //删除的实际是y的位置的结点,要记录y的颜色
            yOriginColor = y.getColor();
            //y可能有右孩子,一定无左孩子,保存右孩子
            x = y.getRight();
            //若y为z的右孩子,直接相连
            if( y.getParent() == z ){
                x.setParent(y);
            }
            //若不相连
            else{
                RB_TRANSPLANT(T, y, y.getRight());
                y.setRight(z.getRight());
                y.getRight().setParent(y);
            }
            RB_TRANSPLANT(T, z, y);
            y.setLeft(z.getLeft());
            y.getLeft().setParent(y);
            y.setColor(z.getColor());
        }
        //删除结点为黑色时需要调整
        if( yOriginColor == NodeColor.Black ){
            RB_DELETE_FIXUP(T, x);
        }
    }
    //删除调整
    public void RB_DELETE_FIXUP(RedBlackTree T, RedBlackTreeNode x){
        //临时结点
        RedBlackTreeNode w = null;
        //非根结点且为黑色
        while( x != T.getRoot() && x.getColor() == NodeColor.Black ){
            //x为父结点左孩子
            if( x == x.getParent().getLeft() ){
                //w为兄弟结点
                w = x.getParent().getRight();
                //case1:w兄弟结点为红色
                if( w.getColor() == NodeColor.Red ){
                    //w设为黑色
                    w.setColor(  NodeColor.Black );
                    //被删结点的父结点设为黑色
                    x.getParent().setColor( NodeColor.Red );
                    //对x的父结点左旋
                    LEFT_ROTATE(T, x.getParent());
                    //更新x的兄弟结点
                    w = x.getParent().getRight();
                }
                //case2:w兄弟结点和两个孩子结点都为黑
                if( w.getLeft().getColor() == NodeColor.Black && w.getRight().getColor() == NodeColor.Black ){
                    //w设为黑色
                    w.setColor(NodeColor.Red);
                    //重设x为x的父结点
                    x = x.getParent();
                }
                //case3:w兄弟结点为黑,w的左孩子为红,右孩子为黑
                else if( w.getRight().getColor() == NodeColor.Black ){
                    //w的左孩子设为黑
                    w.getLeft().setColor(NodeColor.Black);
                    //w设为红
                    w.setColor(NodeColor.Red);
                    //右旋
                    RIGHT_ROTATE(T, w);
                    //更新w
                    w = x.getParent().getRight();
                }
                //case4:w兄弟结点为黑,w的右孩子为红
                w.setColor(x.getParent().getColor());
                x.getParent().setColor(NodeColor.Black);
                w.getRight().setColor(NodeColor.Black);
                LEFT_ROTATE(T, x.getParent());
                x = T.getRoot();
            }
            //x为父结点右孩子
            else{
                w = x.getParent().getLeft();
                if( w.getColor() == NodeColor.Red ){
                    w.setColor(  NodeColor.Black );
                    x.getParent().setColor( NodeColor.Red );
                    RIGHT_ROTATE(T, x.getParent());
                    w = x.getParent().getLeft();
                }
                if( w.getRight().getColor() == NodeColor.Black && w.getLeft().getColor() == NodeColor.Black ){
                    w.setColor(NodeColor.Red);
                    x = x.getParent();
                }
                else if( w.getLeft().getColor() == NodeColor.Black ){
                    w.getRight().setColor(NodeColor.Black);
                    w.setColor(NodeColor.Red);
                    LEFT_ROTATE(T, w);
                    w = x.getParent().getLeft();
                }
                w.setColor(x.getParent().getColor());
                x.getParent().setColor(NodeColor.Black);
                w.getLeft().setColor(NodeColor.Black);
                RIGHT_ROTATE(T, x.getParent());
                x = T.getRoot();
            }
        }
        x.setColor(NodeColor.Black);
    }
    //左旋
    public void LEFT_ROTATE(RedBlackTree T, RedBlackTreeNode x){
        //左旋结点右子树不能为空
        if ( IsNil(x.getRight()) == true )
            return;
        //定义y结点
        RedBlackTreeNode y = x.getRight();
        //y左子树 -> x右子树
        x.setRight(y.getLeft());
        //x -> y左子树父结点
        y.getLeft().setParent(x);
        //x父结点 -> y父结点
        y.setParent(x.getParent());
        //y -> x父结点左/右子树或根结点
        if( IsNil(x.getParent()) == true){
            //x为根结点,y设为根结点
            T.setRoot(y);
        }else if( x.getParent().getLeft() == x){
            //x为左子树,y设为左子树
            x.getParent().setLeft(y);
        }else{
            //x为右子树,y设为右子树
            x.getParent().setRight(y);
        }
        //x -> y左子树
        y.setLeft(x);
        //y -> x父结点
        x.setParent(y);
    }
    //右旋
    public void RIGHT_ROTATE(RedBlackTree T, RedBlackTreeNode x){
        //右旋结点父结点不能为空
        if ( IsNil(x.getParent()) == true )
            return;
        //定义y结点
        RedBlackTreeNode y = x.getParent();
        //x右子树 -> y左子树
        y.setLeft(x.getRight());
        //y -> x右子树父结点
        x.getRight().setParent(y);
        //y父结点 -> x父结点
        x.setParent(y.getParent());
        //x -> y父结点左/右子树或根结点
        if( IsNil(y.getParent()) == true){
            //y为根结点,x设为根结点
            T.setRoot(x);
        }else if( y.getParent().getLeft() == y){
            //y为左子树,x设为左子树
            y.getParent().setLeft(x);
        }else{
            //y为右子树,x设为右子树
            y.getParent().setRight(x);
        }
        //y -> x右子树
        x.setRight(y);
        //x -> y父结点
        y.setParent(x);
    }
    //前序遍历
    public void preorder(RedBlackTreeNode t){
        if(IsNil(t) == false){
            System.out.println(t.getKey());
            preorder(t.getLeft());  
            preorder(t.getRight());  
        }  
    }
    //中序遍历
    public void midorder(RedBlackTreeNode t){
        if(IsNil(t) == false){
            midorder(t.getLeft());
            System.out.println(t.getKey());
            midorder(t.getRight());  
        }  
    }
    //后序遍历
    public void postorder(RedBlackTreeNode t){
        if(IsNil(t) == false){
            postorder(t.getLeft());  
            postorder(t.getRight());  
            System.out.println(t.getKey());
        }  
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        RedBlackTree T = new RedBlackTree();
        RedBlackTreeNode node1 = T.RB_NODE(10);
        T.RB_INSERT(T, node1);
        RedBlackTreeNode node2 = T.RB_NODE(20);
        T.RB_INSERT(T, node2);
        RedBlackTreeNode node3 = T.RB_NODE(30);
        T.RB_INSERT(T, node3);
        T.preorder(T.getRoot());
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年04月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 红黑树算法的Java实现
    • 红黑树
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档