红黑树定义
-
根节点
是黑色的 -
节点要么为红色,要么为黑色
-
任意节点到其
子孙节点
,所经过路径上的包含相同数量的黑色节点 -
红色节点,其子节点不能为红色
-
所有叶子节点皆为黑色,此叶子节点指的是为空(NIL或NULL)的叶子节点,通常省略不画。
红黑树染色,旋转规则
除第一个节点(作为初始根)
颜色为黑色,所有新插入节点
颜色都为红色
。
-
1 若
插入节点
的父节点
为黑色,则直接插入 -
2 若
插入节点
的父节点
为红色- 2.1 若
插入节点
的叔叔节点
为红色,则进行染色,父节点与叔节点转为黑色
,祖父节点转为红色
,矛盾向上转移。
- 2.2 若
插入节点
的叔叔节点
为黑色-
2.2.1 若
插入节点
和父节点
的偏向,与父节点
与其祖父节点
的偏向一致。换句话说,插入节点是其父节点的右(左)子树,且父节点是其插入节点的祖父节点
的右(左)子树,则偏向一致。此时,第一步,将父节点
转为黑色
,祖父节点
转为红色
。第二步,以祖父节点为基准,进行左旋。 -
2.2.2 若
插入节点
和父节点
的偏向,与父节点
与其祖父节点
的偏向不一致
。此时,第一步,先进行节点旋转,以父节点为基准进行右旋,此时致使三个节点偏向一致,然后进行上一种偏向一致
操作。
-
- 2.1 若
-
补充:
- 旋转的本质,其实就是使节点的偏向一致,无非去考虑什么时候左旋,什么时候右旋
- 染色与旋转的规则,都是为定义所服务的
- 一个问题,染色会导致矛盾上移。当上移到根节点的时候,该怎么处理呢
红黑树插入具体示例
以插入int[] a = {10, 18, 16, 12, 13, 17, 15, 14, 9, 8,7}
数组为案例。
- 插入节点10,
初始节点,设为根节点
,颜色为黑
色。
- 插入节点18,颜色为
红
色,因父节点为黑
色,直接插入。
- 插入节点16,颜色为
红
色,因父节点为红
色,且叔叔节点为黑
色(根据定义所有叶子节点皆为黑色
),所以符合2.2.2
条件,先旋转,在染色,在旋转
。
- 插入节点12,颜色为
红
色,因父节点为红
色,且叔叔节点也为红
色,符合2.1
条件,父节点与叔节点变黑
色,祖父节点变红
色,又因为祖父节点为根节点,所以再次变为黑
色(定义:根节点为黑色)。
- 插入节点13,颜色为
红
色,因父节点为红
色,且叔叔节点为黑
色,与插入节点16
情况不同的是,其偏向一致,与2.2.1
条件所描述的相同,所以直接染色,在旋转。
- 插入节点17,颜色为
红
色,因父节点为黑
色,直接插入。
- 插入节点15,颜色为
红
色,因父节点为红
色,且叔叔节点也为红
色,符合2.1
条件,父节点与叔节点变黑
色,祖父节点变红
色,此时,已满足红黑树平衡条件,无需旋转。
- 插入节点14,颜色为
红
色,因父节点为红
色,且叔叔节点为黑
色,且父子节点偏向不一致
。符合2.2.2
条件,先旋转,在染色,在旋转。
- 插入节点9,颜色为
红
色,因父节点为黑
色,直接插入。
- 插入节点8,颜色为
红
色,因父节点为红
色,且叔叔节点为黑
色,且父子节点偏向一致
。符合2.2.1
条件,先染色,在旋转
- 插入节点7,颜色为
红
色,因父节点为红
色,且叔叔节点也为红
色,符合2.1
条件,父节点与叔节点变黑
色,祖父节点变红
色。又因为节点9与节点12处于连续状态,不满足定义,根据2.2.1
条件,节点12
变黑
,节点16
变红
,根据定义任意节点到其子孙节点,所经过路径上的包含相同数量的黑色节点
,所以此时将根节点变为黑色,以不满足定义,故根据2.2.1
,进行旋转。