【数据结构】红黑树(jdk1.8详解)

我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码


一、架构

在这里插入图片描述

二、特性

2.1 二叉查找树的特点

任意一个节点所包含的键值,大于等于左孩子的键值,小于等于右孩子的键值。

2.2 红黑树的特点
  1. 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树。
  2. 节点要么黑色,要么红色
  3. 根节点是黑的
  4. 叶子节点也是黑的 [注意:这里叶子节点,是指为空的叶子节点!]
  5. 如果一个节点是红色的,则它的儿子必须是黑色的。
  6. 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。(确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。)
总结: 非黑即红,头尾是黑,红儿是黑,各路同黑。

=== 点击查看top目录 ===

2.3 红黑树的基本操作
  1. 添加
  2. 删除
  3. 旋转。
  • 为什么要旋转?
  1. 旋转的目的是让树保持红黑树的特性。
  2. 添加或删除红黑树中的节点之后,红黑树就发生了变化,可能不满足红黑树的5条性质,也就不再是一颗红黑树了,而是一颗普通的树。而通过旋转,可以使这颗树重新成为红黑树。
  3. 旋转包括两种:左旋 和 右旋。

=== 点击查看top目录 ===

2.3.1 【左旋】
2.3.1.1 图示与步骤

 height=500 width=500 src="https://i-blog.csdnimg.cn/blog_migrate/2542ce846c5fd84cc00afd57e4ee59ad.gif>

在这里插入图片描述

  1. 先检查 P 是不是空,并且 P 的右边有东西
  2. P 的右指针指向了 Y 的左节点
  3. 原先 Y 的左节点换爸爸
  4. Y 的爸爸换成了 P 的爸爸。由于 P 的爸爸比较顶部,所以假如原先 root (root 指向的节点的爸爸是 null) 指向了 P 话,那么此时 root 改为指向了 Y ,并且由于红黑树性质“头尾是黑”,此时 Y 的节点的 red 肯定是 false
  5. 顶部爸爸换儿子(原先儿子是 P, 现在要变成 Y),先判断原先孩子P到底是左孩子,还是右孩子,然后再替换
  6. Y 的左孩子变成了 P
  7. P 的爸爸变成了 Y

=== 点击查看top目录 ===

2.3.1.2 代码(HashMap1.8)
  • HashMap中红黑树的代码(jdk1.8)
  • java.util.HashMap.TreeNode#rotateLeft
 static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
                                          TreeNode<K,V> p) {
     
    TreeNode<K,V> y, pp, yl;
   	// 1. 先检查 P 是不是空,并且 P的右边有东西
    if (p != null && (y = p.right) != null) {
     
    	// 2. P 的右指针指向了 Y 的左节点
        if ((yl = p.right = y.left) != null)
        	// 3.原先 Y 的左节点换爸爸 
            yl.parent = p;
        // 4. Y 的爸爸换成了 P 的爸爸。
        if ((pp = y.parent = p.parent) == null)
        	// 假如 “原先 root 指向 P”,进入此代码
            (root = y).red = false;
        // 5.  顶部爸爸换儿子(原先儿子是 P, 现在要变成 Y)
        // 先判断原先孩子P到底是左孩子,还是右孩子,然后再替换
        else if (pp.left == p)
        	// 原先是左孩子
            pp.left = y;
        else
 			// 原先是右孩子
            pp.right = y;
        // 6. Y 的左孩子变成了 P
        y.left = p;
        // 7. P  的爸爸变成了 Y
        p.parent = y;
    }
    return root;
}

=== 点击查看top目录 ===

2.3.2 【右旋】
2.3.2.1 图示与步骤

在这里插入图片描述
在这里插入图片描述

  1. 先检查 P 是否为空,并且检查 P 是否有左孩子
  2. P 的左指针指向了 X 的右孩子
  3. 原先 X 的右节点换爸爸
  4. X 的爸爸换成了 P 的爸爸。由于 P 的爸爸比较顶部,所以假如原先 root (root 指向的节点的爸爸是 null) 指向了 P 话,那么此时 root 改为指向了 Y ,并且由于红黑树性质“头尾是黑”,此时 Y 的节点的 red 肯定是 false
  5. 顶部爸爸换儿子(原先儿子是 P, 现在要变成 Y),先判断原先孩子P到底是左孩子,还是右孩子,然后再替换
  6. X 的右儿子变成 P
  7. P 的爸爸变成了 X

=== 点击查看top目录 ===

2.3.2.2 代码(HashMap1.8)
  • HashMap中红黑树的代码(jdk1.8)
  • java.util.HashMap.TreeNode#rotateRight
  static <K,V> HashMap.TreeNode<K,V> rotateRight(HashMap.TreeNode<K,V> root,
                                                   HashMap.TreeNode<K,V> p) {
     
        HashMap.TreeNode<K,V> x, pp, lr;
        // 1. 先检查 P 是否为空,并且检查 P 是否有左孩子
        if (p != null && (x = p.left) != null) {
     
        	// 2. P 的左指针指向了 X 的右孩子
            if ((lr = p.left = x.right) != null)
            	// 3. 原先 X 的右节点换爸爸 
                lr.parent = p;
            // 4. X 的爸爸换成了 P 的爸爸
            if ((pp = x.parent = p.parent) == null)
            	 // 假如 “原先 root 指向 P”,进入此代码
                (root = x).red = false;
            else if (pp.right == p)
                // 原先是右孩子
                pp.right = x;
            else
                // 原先是左孩子
                pp.left = x;
            // 6. X 的右儿子变成 P
            x.right = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值