当前位置:首页 > 经验 >

红黑树的高度和深度区别(红黑树的原理动态图)

来源:原点资讯(www.yd166.com)时间:2022-11-14 14:34:32作者:YD166手机阅读>>

右右节点旋转(插入节点的父节点是右节点,插入节点也是右节点)

还是来上面的图来举例,我们在这颗红黑树上插入节点 70 。

红黑树的高度和深度区别,红黑树的原理动态图(29)

我们可以这样操作围绕祖父节点 66 左旋,再把旋转后的根节点 69 设置为黑色,把 66 这个节点设置为红色。具体可以参看下图:

红黑树的高度和深度区别,红黑树的原理动态图(30)

红黑树在 Java 中的实现

Java 中的红黑树实现类是 TreeMap ,接下来我们尝试从源码角度来逐行解释 TreeMap 这一套机制是如何运作的。

// TreeMap中使用Entry来描述每个节点

static final class Entry<K,V> implements Map.Entry<K,V> {

K key;

V value;

Entry<K,V> left;

Entry<K,V> right;

Entry<K,V> parent;

boolean color = BLACK;

...

}

TreeMap 的put方法。

public V put(K key, V value) {

//先以t保存链表的root节点

Entry<K,V> t = root;

//如果t=null,表明是一个空链表,即该TreeMap里没有任何Entry作为root

if (t == null) {

compare(key, key); // type (and possibly null) check

//将新的key-value创建一个Entry,并将该Entry作为root

root = new Entry<>(key, value, null);

size = 1;

//记录修改次数加1

modCount ;

return null;

}

int cmp;

Entry<K,V> parent;

// split comparator and comparable paths

Comparator<? super K> cpr = comparator;

//如果比较器cpr不为null,即表明采用定制排序

if (cpr != null) {

do {

//使用parent上次循环后的t所引用的Entry

parent = t;

//将新插入的key和t的key进行比较

cmp = cpr.compare(key, t.key);

//如果新插入的key小于t的key,t等于t的左边节点

if (cmp < 0)

t = t.left;

//如果新插入的key大于t的key,t等于t的右边节点

else if (cmp > 0)

t = t.right;

else

//如果两个key相等,新value覆盖原有的value,并返回原有的value

return t.setValue(value);

} while (t != null);

}

else {

if (key == null)

throw new NullPointerException();

@SuppressWarnings("unchecked")

Comparable<? super K> k = (Comparable<? super K>) key;

do {

parent = t;

cmp = k.compareTo(t.key);

if (cmp < 0)

t = t.left;

else if (cmp > 0)

t = t.right;

else

return t.setValue(value);

} while (t != null);

}

//将新插入的节点作为parent节点的子节点

Entry<K,V> e = new Entry<>(key, value, parent);

//如果新插入key小于parent的key,则e作为parent的左子节点

if (cmp < 0)

parent.left = e;

//如果新插入key小于parent的key,则e作为parent的右子节点

else

parent.right = e;

//修复红黑树

fixAfterInsertion(e);

size ;

modCount ;

return null;

}

//插入节点后修复红黑树

private void fixAfterInsertion(Entry<K,V> x) {

x.color = RED;

//直到x节点的父节点不是根,且x的父节点是红色

while (x != null && x != root && x.parent.color == RED) {

//如果x的父节点是其父节点的左子节点

if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {

//获取x的父节点的兄弟节点

Entry<K,V> y = rightOf(parentOf(parentOf(x)));

//如果x的父节点的兄弟节点是红色

if (colorOf(y) == RED) {

//将x的父节点设置为黑色

setColor(parentOf(x), BLACK);

//将x的父节点的兄弟节点设置为黑色

setColor(y, BLACK);

//将x的父节点的父节点设为红色

setColor(parentOf(parentOf(x)), RED);

x = parentOf(parentOf(x));

}

//如果x的父节点的兄弟节点是黑色

else {

//TODO 对应情况第二种,左右节点旋转

//如果x是其父节点的右子节点

if (x == rightOf(parentOf(x))) {

//将x的父节点设为x

x = parentOf(x);

//右旋转

rotateLeft(x);

}

//把x的父节点设置为黑色

setColor(parentOf(x), BLACK);

//把x的父节点父节点设为红色

setColor(parentOf(parentOf(x)), RED);

rotateRight(parentOf(parentOf(x)));

}

}

//如果x的父节点是其父节点的右子节点

else {

//获取x的父节点的兄弟节点

Entry<K,V> y = leftOf(parentOf(parentOf(x)));

//只着色的情况对应的是最开始例子,没有旋转操作,但是要对应多次变换

//如果x的父节点的兄弟节点是红色

if (colorOf(y) == RED) {

//将x的父节点设置为黑色

setColor(parentOf(x), BLACK);

//将x的父节点的兄弟节点设为黑色

setColor(y, BLACK);

//将X的父节点的父节点(G)设置红色

setColor(parentOf(parentOf(x)), RED);

//将x设为x的父节点的节点

x = parentOf(parentOf(x));

}

//如果x的父节点的兄弟节点是黑色

else {

//如果x是其父节点的左子节点

if (x == leftOf(parentOf(x))) {

//将x的父节点设为x

x = parentOf(x);

//右旋转

rotateRight(x);

}

//将x的父节点设为黑色

setColor(parentOf(x), BLACK);

//把x的父节点的父节点设为红色

setColor(parentOf(parentOf(x)), RED);

rotateLeft(parentOf(parentOf(x)));

}

}

}

//将根节点强制设置为黑色

root.color = BLACK;

}

TreeMap的插入节点和普通的排序二叉树没啥区别,唯一不同的是,在TreeMap 插入节点后会调用方法fixAfterInsertion(e)来重新调整红黑树的结构来让红黑树保持平衡。

我们重点关注下红黑树的fixAfterInsertion(e)方法,接下来我们来分别介绍两种场景来演示fixAfterInsertion(e)方法的执行流程。

第一种场景:只需变色即可平衡

同样是拿这颗红黑树举例,现在我们插入节点 51。

红黑树的高度和深度区别,红黑树的原理动态图(31)

当我们需要插入节点51的时候,这个时候TreeMap 的 put 方法执行后会得到下面这张图。

红黑树的高度和深度区别,红黑树的原理动态图(32)

栏目热文

红黑树与b+树区别(红黑树解决什么问题)

红黑树与b+树区别(红黑树解决什么问题)

树的定义树是包含n(n>1)个结点,n-1条边的有穷集,其中:(1)每个元素称为结点;(2)有一个特定的结点称为根...

2022-11-14 14:55:20查看全文 >>

红黑树和平衡二叉树的优缺点(红黑树为什么是平衡二叉树)

红黑树和平衡二叉树的优缺点(红黑树为什么是平衡二叉树)

1 引言预防针:红黑树本来就是基本算法中的难点,所以看此文时建议先有点预备心理或知识铺垫,没接触过RBT而直接看此文的话...

2022-11-14 14:09:12查看全文 >>

红黑树为什么叫平衡二叉树(详解什么是平衡二叉树)

红黑树为什么叫平衡二叉树(详解什么是平衡二叉树)

前言面试过程中,多多少少会问一点数据结构(二叉树)的问题,今天我们来复习一下二叉树的相关问题,文末总结。1. 二叉树的由...

2022-11-14 14:52:59查看全文 >>

二叉树和红黑树(二叉树和树的关系)

二叉树和红黑树(二叉树和树的关系)

红黑树在工程中的使用,红黑树是平衡树的一种。1. 红黑树顺序的功能2. 快速查找的功能1.二叉树插入1. 如果比当前根节...

2022-11-14 14:17:23查看全文 >>

为什么用红黑树而不是二叉树(红黑树和二叉树优缺点)

为什么用红黑树而不是二叉树(红黑树和二叉树优缺点)

上两节,我们依次讲了树、二叉树、二叉查找树。二叉查找树是最常用的一种二叉树,它支持快速插入、删除、查找操作,各个操作的时...

2022-11-14 14:26:38查看全文 >>

红黑树二叉树的区别(红黑树和平衡二叉树区别)

红黑树二叉树的区别(红黑树和平衡二叉树区别)

很早之前就想写一篇关于红黑树的文章,但是由于担心自己理解的不透彻,就一直不敢下笔。于是在重新看了很多篇文章和资料之后,决...

2022-11-14 14:11:33查看全文 >>

红黑树与平衡二叉树的区别(红黑树平衡树对比)

红黑树与平衡二叉树的区别(红黑树平衡树对比)

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。简单说就是可用于二分查找的(二叉查找树),且高度是平衡的(...

2022-11-14 14:54:56查看全文 >>

红黑树一定是平衡二叉树吗(红黑树是一个平衡的二叉排序树)

红黑树一定是平衡二叉树吗(红黑树是一个平衡的二叉排序树)

二叉搜索树的局限性 上一节较为详细的介绍了C语言中的二叉搜索树,提到数据采取二叉搜索树的结构存储,可以获得不错的搜索性能...

2022-11-14 14:51:45查看全文 >>

有序树和二叉树的区别(二叉判定树和二叉排序树的区别)

有序树和二叉树的区别(二叉判定树和二叉排序树的区别)

树这些基本的东西必须了解一下!数据结构之树的一些事儿树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据...

2022-11-14 14:19:14查看全文 >>

马拉松赛前一个月怎么训练计划(马拉松赛前一周怎么安排)

马拉松赛前一个月怎么训练计划(马拉松赛前一周怎么安排)

2019宜昌国际马拉松暨全国马拉松锦标赛(宜昌站),将于10月27日上午7:30在湖北宜昌市鸣枪。宜昌国际马拉松创办于2...

2022-11-14 14:25:32查看全文 >>

文档排行