Java红黑树

作者: 汤姆torn | 来源:发表于2020-07-22 17:03 被阅读0次

首先创建树结构

class Node {
    final boolean RED = true;
    final boolean BLACK = false;
    int key;
    boolean color;
    Node left, right, parent;

    public Node(int key) {
        this.key = key;
        this.color = RED;
    }

    @Override
    public String toString() {
        String str = "[";
        if (this.color == RED) {
            str += "红色";
        } else {
            str += "黑色";
        }
        return str + "," + this.key + "]";
    }
}

创建红黑树类

public class RBTree {
    final boolean RED = true;
    final boolean BLACK = false;
    Node root = null;
    
}

插入方法

      public void insertNode(int key){
        Node node = new Node(key);
        if(root == null){    //判断根节点是否为空,如果为空,当前节点即为根节点,并把颜色赋成黑色
            root = node;
            root.color = BLACK;
        }else{            //不是根节点,寻找可以当做父节点的节点
            Node cur = root;
            Node parent = null;
            do {
                parent = cur;
                if(parent.key >= key){
                    cur = cur.left;
                }else{
                    cur = cur.right;
                }
            }while (cur != null);  //找到父节点之后,判断是在左边还是右边
            node.parent = parent;
            if(parent.key >= key){
                parent.left = node;
            }else{
                parent.right = node;
            }
        }
        balanceSelf(node); //每次插入要进行自平衡
    }

在插入的时候,要进行自平衡,那么就要涉及到几个原子操作:左旋/右旋,变色


左旋

图中的左旋,我们注意到,只有3个地方变了(不要纠结颜色,原子操作互不干扰)
①X的父亲变成了Z的父亲
②Z的左子树从A变成了X
③X的右子树变成了A
左旋方法就很简单了

  public void rotateToLeft(Node node) {//把node看成X
        Node x = node;
        Node z = x.right;
        if (z.left != null) {
            // 如果z的左子树不为空
            z.left.parent = x;

        }
        x.right = z.left;
        if (x.parent == null) {//如果是根节点
            root = z;
        } else if (x.parent.left == x) {//如果x是x父亲的左子树
            x.parent.left = z;
        } else {
            x.parent.right = z;
        }
        z.parent = x.parent;
        //建立z和x之间的父子关系
        x.parent = z;
        z.left = x;
    }

右旋和左旋相左就是


右旋

右旋

     public void rotateToRight(Node node) {
        Node x = node;
        Node y = node.left;
        if (y.right != null) {
            y.right.parent = x;
        }
        x.left = y.right;
        if (x.parent == null) {
            root = y;
        } else if (x.parent.left == x) {
            x.parent.left = y;
        } else {
            x.parent.right = x;
        }
        y.parent = x.parent;
        x.parent = y;
        y.right = x;
    }

能左旋右旋变色,就可以进行自平衡了

  private void balanceSelf(Node node) {
        Node parent,grandParent;
        //父存在并红色,因为刚插入的数据是红色,所以形成了红 红,要进行自平衡
        while((parent = node.parent)!= null && parent.color == RED){
            grandParent = parent.parent;
            //判断父是祖父的左子树还是右子树,目的是为了找出叔叔节点
            if(parent == grandParent.left){
                Node uncle = grandParent.right;

                //case 1 : 叔叔存在并红色
                if(null != uncle && uncle.color == RED){
                    uncle.color = BLACK;
                    parent.color = BLACK;
                    grandParent.color = RED;
                    node = grandParent;  //把祖父又当成X向上回溯
                    continue;
                }

                //case 2 : 叔叔黑,当前节点是右孩子
                if(parent.right == node){
                    rotateToLeft(parent);
                    Node temp = parent;
                    parent = node;
                    node = temp;
                }

                //case 3 : 叔叔黑,当前是左孩子
                parent.color = BLACK;
                grandParent.color = RED;
                rotateToRight(grandParent);

            }else{
                Node uncle = grandParent.left;

                //case 1 : 叔叔存在并红色
                if(null != uncle && uncle.color == RED){
                    uncle.color = BLACK;
                    parent.color = BLACK;
                    grandParent.color = RED;
                    node = grandParent;  //把祖父又当成X向上回溯
                    continue;
                }

                //case 2 : 叔叔黑,当前节点是左孩子
                if(parent.left == node){
                    rotateToRight(parent);
                    Node temp = parent;
                    parent = node;
                    node = temp;
                }

                //case 3 : 叔叔黑,当前是右孩子
                parent.color = BLACK;
                grandParent.color = RED;
                rotateToLeft(grandParent);

            }
        }
        root.color = BLACK; // 根节点黑色
    }

删除------
全代码

public class RBTree {
    final boolean RED = true;
    final boolean BLACK = false;
    Node root = null;

    public void insertNode(int key) {
        Node node = new Node(key);
        if (root == null) {    //判断根节点是否为空,如果为空,当前节点即为根节点,并把颜色赋成黑色
            root = node;
            root.color = BLACK;
        } else {            //不是根节点,寻找可以当做父节点的节点
            Node cur = root;
            Node parent = null;
            do {
                parent = cur;
                if (parent.key >= key) {
                    cur = cur.left;
                } else {
                    cur = cur.right;
                }
            } while (cur != null);  //找到父节点之后,判断是在左边还是右边
            node.parent = parent;
            if (parent.key >= key) {
                parent.left = node;
            } else {
                parent.right = node;
            }
        }
        balanceSelf(node);
    }

    public void rotateToLeft(Node node) {//把node看成X
        Node x = node;
        Node z = x.right;
        if (z.left != null) {
            // 如果z的左子树不为空
            z.left.parent = x;

        }
        x.right = z.left;
        if (x.parent == null) {//如果是根节点
            root = z;
        } else if (x.parent.left == x) {//如果x是x父亲的左子树
            x.parent.left = z;
        } else {
            x.parent.right = z;
        }
        z.parent = x.parent;
        //建立z和x之间的父子关系
        x.parent = z;
        z.left = x;
    }

    public void rotateToRight(Node node) {
        Node x = node;
        Node y = node.left;
        if (y.right != null) {
            y.right.parent = x;
        }
        x.left = y.right;
        if (x.parent == null) {
            root = y;
        } else if (x.parent.left == x) {
            x.parent.left = y;
        } else {
            x.parent.right = x;
        }
        y.parent = x.parent;
        x.parent = y;
        y.right = x;
    }


    private void balanceSelf(Node node) {
        Node parent, grandParent;
        //父存在并红色,因为刚插入的数据是红色,所以形成了红 红,要进行自平衡
        while ((parent = node.parent) != null && parent.color == RED) {
            grandParent = parent.parent;
            //判断父是祖父的左子树还是右子树,目的是为了找出叔叔节点
            if (parent == grandParent.left) {
                Node uncle = grandParent.right;

                //case 1 : 叔叔存在并红色
                if (null != uncle && uncle.color == RED) {
                    uncle.color = BLACK;
                    parent.color = BLACK;
                    grandParent.color = RED;
                    node = grandParent;  //把祖父又当成X向上回溯
                    continue;
                }

                //case 2 : 叔叔黑,当前节点是右孩子
                if (parent.right == node) {
                    rotateToLeft(parent);
                    Node temp = parent;
                    parent = node;
                    node = temp;
                }

                //case 3 : 叔叔黑,当前是左孩子
                parent.color = BLACK;
                grandParent.color = RED;
                rotateToRight(grandParent);

            } else {
                Node uncle = grandParent.left;

                //case 1 : 叔叔存在并红色
                if (null != uncle && uncle.color == RED) {
                    uncle.color = BLACK;
                    parent.color = BLACK;
                    grandParent.color = RED;
                    node = grandParent;  //把祖父又当成X向上回溯
                    continue;
                }

                //case 2 : 叔叔黑,当前节点是左孩子
                if (parent.left == node) {
                    rotateToRight(parent);
                    Node temp = parent;
                    parent = node;
                    node = temp;
                }

                //case 3 : 叔叔黑,当前是右孩子
                parent.color = BLACK;
                grandParent.color = RED;
                rotateToLeft(grandParent);

            }
        }
        root.color = BLACK; // 根节点黑色
    }

    public void inOrder() {
        this.inOrder(root);
    }

    public void inOrder(Node node) {
        if (node == null) {
            return;
        }
        inOrder(node.left);
        System.out.println(node);
        inOrder(node.right);
    }
}


class Node {
    final boolean RED = true;
    final boolean BLACK = false;
    int key;
    boolean color;
    Node left, right, parent;

    public Node(int key) {
        this.key = key;
        this.color = RED;
    }

    @Override
    public String toString() {
        String str = "[";
        if (this.color == RED) {
            str += "红色";
        } else {
            str += "黑色";
        }
        return str + "," + this.key + "]";
    }
}

相关文章

  • 数据结构学习_02红黑树平衡操作

    参考文章 : 红黑树原理解析以及Java实现 红黑树(五)之 Java的实现 废话不多说, 直接开始分析 一、红黑...

  • Java集合源码分析之Map(四):TreeMap

    TreeMap是红黑树的java实现,对红黑树不太了解的可以查阅这篇文章Java集合源码分析之基础(六):红黑树(...

  • 算法与数据结构系列之[红黑树-下]

    上篇介绍了红黑树的概述,这篇贴出红黑树的java实现代码。

  • 红黑树笔记

    红黑树:R-B Tree [toc]参考:红黑树(一)之 原理和算法详细介绍红黑树(五)之 Java的实现 1 简...

  • 红黑树

    红黑树 红黑树是一中重要的二叉平衡树 这里主要以JAVA...

  • 红黑树

    红黑树图Java在实现TreeMap中用到了红黑树,在此记录自己的理解。 定义 红黑树是二叉搜索树的一种实现方式,...

  • 头条一面 java

    1、java gc 2、javaclass的加载过程 3、javahashmap、为什么用红黑树、红黑树邻接点为啥...

  • Java基础知识

    1、java gc 2、javaclass的加载过程 3、javahashmap、为什么用红黑树、红黑树邻接点为啥...

  • 【Java】红黑树

    1 平衡二叉树 平衡二叉树性质: 它的左右两个子树都是平衡数,且左右两个子树的高度差的绝对值不超过1若将二叉树节点...

  • Java红黑树

    首先创建树结构 创建红黑树类 插入方法 在插入的时候,要进行自平衡,那么就要涉及到几个原子操作:左旋/右旋,变色 ...

网友评论

    本文标题:Java红黑树

    本文链接:https://www.haomeiwen.com/subject/adhtlktx.html