java红黑树

红黑树描述

红黑树是一种二叉树,树上的节点分为红色和黑色两种。通过对节点的规则约束,保证每个节点到叶子节点的路径不会相差两倍。红黑树比较复杂,但是它在最坏的情况下,也能保持比较高的效率。

红黑树特点

  1. 每个节点要么是红的,要么是黑的
  2. 根节点一定是黑的
  3. 每个叶子节点一定是黑的
  4. 如果一个节点时红的,那么他的叶节点一定是黑的
  5. 每个节点到期子孙叶子节点的路径上所经过的黑色节点数量一致

红黑树旋转

左旋

以B和E的连接为轴,将右侧子节点E向上移动(逆时针旋转)作为父节点

《java红黑树》

左旋步骤:

1.节点E的父节点(即A)指向节点B的父节点(即A)

2.若节点E的父节点A为空,则节点E将成为新的root节点;如果左旋之前A的左节点为节点B,则现在将A的左节点指向节点E;如果之前A的右节点为节点B,则现在将A的右节点指向节点E

3.将节点E的左节点指向节点B

4.将节点2的父节点指向节点B

5.将节点B的右节点指向节点2

6.将节点B的父节点指向节点E

代码实现如下:

public class TreeMap{
    
    private Node root;//根节点

    private void rotateLeft(Node node){
         Node newRoot = node.right;
         newRoot.parent = node.parent;//节点node的父节点变为节点node.right(newRoot)的父节点
         Node A = newRoot.parent;//设置newRoot的父节点为A(即原来节点node的父节点)
         if(A == null){//如果A为空,则表示原来node是根节点,则newRoot现在也应该是根节点
             root = newRoot;
         }else if(A.left == node){//如果A的左节点指向node,则现在A的左节点应该指向newRoot
             A.left = newRoot;
         }else if(A.right == node){//如果A的右节点指向node,则现在A的右节点应该指向newRoot
             A.right = newRoot;
         }
         node.parent = newRoot;//节点newRoot变为节点node的父节点
         newRoot.left.parent = node;//节点newRoot的左节点的父节点指向节点node
         node.right = newRoot.left;//节点node的右节点指向节点newRoot的左节点
         newRoot.left = node;//节点newRoot的左节点指向node
    }
}

class Node{
   Node left;
   Node right;
   Node parent;
}

​右旋

以节点E和节点B的连接为轴,将节点E向下移(顺时针旋转)变为子节点

《java红黑树》

右旋

1.节点B的父节点(即节点A)指向节点E的父节点(即节点A)

2.若发现当前B父节点A为空,则节点B将成为新的root节点;如果节点A的左节点之前为节点E,则现在A的左节点指向节点B;如果A的右节点之前为节点E,则现在A的右节点指向节点B

3.节点2的父节点指向节点E

4.节点E的左节点指向节点2

5.节点B的右节点指向节点E

6.节点E的父节点指向节点B

代码实现如下:

public class TreeMap{

   private Node root;//根节点

   private void rotateRight(Node node){
        Node oldRoot = node.parent;
        node.parent = oldRoot.parent;//节点node的父节点指向节点node.parent(oldRoot)的父节点
        Node A = node.parent;//设置node的父节点为节点A
        if(A == null){//如果原来oldRoot是根节点,那么现在node也应该是根节点
           root = node;
        }else if(A.left == oldRoot){//如果原来A的左节点是oldRoot,那么现在A的左节点应该是node
           A.left = node;
        }else if(A.right == oldRoot){//如果原来A的右节点时oldRoot,那么现在A的右节点应该是node
           A.right = node;
        }
        oldRoot.left = node.right;//节点oldRoot的左节点指向node的右节点
        node.right.parent = oldRoot;//节点node右节点的父节点指向oldRoot
        node.right = oldRoot;//节点node的右节点指向节点oldRoot
        oldRoot.parent = node;//节点oldRoot的父节点指向node
   }

}

class Node{
    Node left;
    Node right;
    Node parent;
}

红黑树操作

插入

注意事项:

1.新插入的节点,一开始是没有颜色的,但是由于红黑要求每个节点都应该有颜色,所以在插入后要给节点涂色。颜色只有两种——黑色和红色。如果选择黑色的话,由于红黑要求任意节点往下的路径长度(黑色节点的数量)一致,会造成新插入节点的父节点(以及再往上的节点)到下面节点的路径长度不同(不平衡),这时候就需要进行路径的调整;如果选择红色的话,由于红色节点不计入路径长度,那么不管插入哪里,路径都是不会变化的。当然红色节点在红黑数据也有限制——红色节点下面的子节点一定是黑色,所以遇到插入节点的父节点也是红色的时候,也需要进行调整。两者相比较的话,选择黑色是一定要调整的,选择红色的是有可能需要调整,所以选择红色会更加划算一些。在红黑树的调整算法中,新插入节点都会选择红色的。

2.新插入节点会通过比较算法,最终成为某个节点的叶子节点(没有子节点),所以在调整时不需要考虑新插入节点的子节点情况

插入的几种情况:

1.新插入节点的父节点为黑色

在这种情况下新插入的节点对树是没有影响的,因为没有违反红黑树的规则。

2.新插入节点的父节点为红色

在这种情况下由于新插入节点是红色的,导致违反了红黑的规则。需要对红黑树进行调整。

删除

 

    原文作者:红黑树
    原文地址: https://my.oschina.net/u/241670/blog/832274
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞