红黑树定义
-
根节点是黑色的 -
节点要么为红色,要么为黑色
-
任意节点到其
子孙节点,所经过路径上的包含相同数量的黑色节点 -
红色节点,其子节点不能为红色
-
所有叶子节点皆为黑色,此叶子节点指的是为空(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,进行旋转。