1、基本介绍:
红黑树是一种平衡查找二叉树,在最坏的情况下基本操作(查找、前续、后继、最小值、最大值、插入、删除)时间为O(logn)。效率高于链表,低于hash表。用途广泛,比如:标准C++中的MAP成员的组织形式就是红黑树,linux内核对内存块(mm_struct)的组织形式也是红黑树。红黑树的性质:
1)、所有节点要么为红色,要么为黑色;
2)、根节点为黑色;
3)、叶子节点为nil,都为黑色;
4)、红色节点的孩子一定是黑色的;
5)、对于每个节点,从该节点到其子孙叶子节点的所有路径上包含相同数目的黑节点。
红黑树的基本操作和普通查找二叉树类似,最主要的区别就是操作过程中,尽量减小对红黑树性质的影响,操作之后维护红黑树的性质。
2、基本操作:
为了维护在操作过程中,保持查找二叉树的性质,引入红黑树的基本操作:左旋和右旋。这两个操作过程中,如果伴随着颜色改变,就能尽量保持红黑树的性质。这两个操作类似于数组的两个成员之间交换数值一样,是最基本的操作。
在基本操作中,只有插入和删除会改变红黑树的性质,《算法导论》在这两个操作之后,引入了INSERT-FIXUP()和DELETE-FIXUP(),也是插入和删除的主要操作。
3、INSERT-FIXUP()
为了尽量减小对红黑树性质的影响,插入的节点x,颜色赋值为红色,这样只有可能影响:性质2)、4).为了恢复性质。对于性质4,直接对根节点的颜色赋值为黑色即可。
修复性质2涉及x,x的父节点、x的父节点的父节点、x的叔叔节点。当x的父节点为红色时,需要修复。当x的父节点为左孩子和右孩子时,分别有三种情况(以x的父节点为左孩子为例):
1)、x的叔叔节点是红色:对x的父节点的父节点赋值为红色,x的父节点和叔叔节点着色为黑色,将x的父节点的父节点赋值给x,再对x节点继续修复性质4);
2)、x的叔叔是黑色,x是右孩子:对x的父节点左旋,变成性质3;
3)、x的叔叔是黑色,x是左孩子:将x的父节点着色为黑色,x的父节点的父节点着色为红色,对x的父节点的父节点进行右旋,修复性质4)
当x的父节点为右孩子时,对称操作。
4、DELETE-FIXUP()
为了尽量减小对红黑树性质的影响,删除节点x时,需要分情况而定:当x双子不健全时,直接删除x节点;当x双子健全时,删除x的直接后继,并将x的后继的key赋值给x的key,操作的结果也是将key为x->key的节点删除了。如果被删除节点颜色为黑色,需要修复红黑树,并且只需要修复性质5),设占据被删除节点位置的节点为y,因为这时候y为承担着两重颜色身份:即是红又是黑,或者是双黑,修复的主要目的是将这份兼备的黑色稀释出来,设计的节点有:y、y的父节点、y的兄弟节点,以及y兄弟节点的孩子。以y为左孩子为例,分情况而定:
1)、y的兄弟为红色,改变父节点和兄弟节点的颜色,并对y的父节点左旋,将y的兄弟编程黑色;进入情况2)、3)或者4);
2)、y的兄弟为黑色,兄弟的双子为黑色:将y的兄弟节点着色为红色,对y的父节点,调用DELETE-FIXUP;
3)、y的兄弟为黑色,y兄弟的左儿子为红色,右儿子为黑色:对y的兄弟着色为红色,左儿子着色为黑色,对y的兄弟右旋操作,进入性质4);
4)、y的兄弟为黑色,y兄弟的右儿子为红色:交换y父节点和y兄弟的颜色,并将y兄弟的右儿子着色为黑色,对y的父节点左旋操作,这时候y所在分支上增加了一抹黑色,即分担了y中的黑色,便修复了性质5)
y为右孩子时,对称操作。