所有被插入的结点一开始都被设置成红色(很重要!),它的左右孩子结点都是NULL,所有的NULL结点被设置为黑色,这样可以满足第3条属性(所有的叶子结点不包含数据,也就是指NULL,并且都是黑色)。
一开始,N正是要被插入的新结点,但是整个过程也可能会迭代到其他的结点上。标志P(Parent)代表N的父结点,标志G(Grand parent)代表N的祖父结点,标志U代表N的叔父结点(Uncle)。
红黑树的插入操作有以下5种情形需要处理:
case 1:N是根结点
case 2:N的父结点(P)是黑色的
case 3:N的父结点(P)和叔父结点(U)是红色的
case 4:N被插入到祖父结点(G)的左子结点的右子结点,或者被插入到祖父结点(G)的右子结点的左子结点,也即N和父结点P的左右位置不同。(此时父结点(P)是红色的,叔父结点(U)是黑色的)
case 5:N被插入到祖父结点(G)的左子结点的左子结点,或者被插入到祖父结点(G)的右子结点的右子结点,也即N和父结点P的左右位置相同。(此时父结点(P)是红色的,叔父结点(U)是黑色的)
下面是每一种情形的具体操作方式:
case 1:
当前结点N是根结点,此时将N的颜色涂为黑色,这样可以满足第2条属性(根结点为黑色)。将根结点设为黑色为每条路径都增加了一个黑色结点,所以性质5没有被违反。
case 2:
被插入结点(N)的父结点(P)是黑色的,所以第4条属性(红色结点的孩子结点都是黑色)没有被违反(假设父结点是红色的,那么由于新插入的结点也是红色的,这样就出现父结点和子结点同时为红色的情况,这将违反属性4)。同时第5条属性也没有被违反,因为插入的是红色结点,所以并没有增加黑色结点的数量(这里也可以理解为用插入的红色结点(带有左右两个空的黑色结点)代替了之前的空的黑色叶子结点,两种理解方式是等价的)。
所以这种情形不做任何处理,简单的返回即可。
注意下面的情形(从case 3开始)可以断定N肯定有一个祖父结点G,因为在以下情形中,父结点P是红色的,所以父结点P不可能是根结点(因为根结点必须是黑色的),由此可推出N肯定有一个祖父结点G。这样N就有一个叔父结点U,尽管U有可能是一个空的黑色叶子结点。
注意:图中的小三角表示一棵子树,小三角上面的黑色圆点表示通过该棵子树的黑色结点数目比没有通过黑色圆点子树的多1。蓝色箭头左边的树中的结点上蓝色的外圈表示本次要处理的结点,箭头右边的树中的结点上蓝色的外圈(如果有的话)表示下次要处理的结点(或下次迭代的结点)。
case 3:
父结点P和叔父结点U都是红色的,此时将父结点P和叔父结点U设为黑色,与此同时,祖父结点必须要设置成红色,这样通过祖父结点的路径的黑色结点数目才不发生改变(为满足属性5)。
然而,祖父结点设成红色之后有可能违反属性2(根结点必须为黑色,若祖父结点恰好是根结点则会违反)或者属性4(当祖父结点的父结点也是红色时,则出现父子都为红色的非法情形)。为了修复这些非法情形,整个过程将转到case 1从祖父结点G开始迭代(或递归)。
在下面的情形(case 4和case 5),假设父结点P是其父亲的左子结点,右子结点的情况与之对称,只需将“左”和“右”对调即可。
case 4:
父结点P是红色的,叔父结点U是黑色的,当前结点N是P的右子结点,P是N的祖父结点G的左子结点。这将违反属性4,因为当前结点N和父结点P都是红色的。此时将父结点P左旋,这样将会调换N和P的角色,注意属性4依然被违反,但是属性5一直被保持。左旋后就变成case 5了,那就交给case 5去处理吧。
case 5:
父结点P是红色的,叔父结点是黑色的,当前结点N是P的左子结点,P也是N的祖父结点G的左子结点(注意这也是和case 4的不同点)。此时将P和G的颜色对调,然后将G右旋。之前所有通过黑色结点G的路径现在都变成通过黑色结点P了,所以满足了第5条属性,由于对调了P和G的颜色,所以父子结点同为红色的情形被修复了,也就满足了第4条属性。
好了,到这一步为止插入过程就全部完成了。
下面通过具体分析每一步的操作来理解插入过程,将每一步操作之后的树结构打印出来可以帮助我们理解,在图中"#"表示黑色,"~"表示红色,空结点(NULL)都为黑色,但是没有被打印出来,看图像的时候注意一下就可以了。整个过程如下所示,所有的步骤都是通过程序实现的,插入的数值是随机的,但是上面的5种情形都出现了。在处理5种情形之前,先将结点插入到合适的叶子位置(插入之后要满足二叉搜索树的属性)。
Inserting 61 -----------------------------------------------------
case 1 <61> (若当前结点是根结点,则将其颜色设置为黑色) :
~61~
result:
#61#
Inserting 9 -----------------------------------------------------
case 1 <9> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#
|
~9~
case 2 <9> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#
|
~9~
result:
_#61#
|
~9~
Inserting 267 -----------------------------------------------------
case 1 <267> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#_
| |
~9~ ~267~
case 2 <267> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#_
| |
~9~ ~267~
result:
_#61#_
| |
~9~ ~267~
Inserting 107 -----------------------------------------------------
case 1 <107> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#______
| |
~9~ _~267~
|
~107~
case 2 <107> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#______
| |
~9~ _~267~
|
~107~
case 3 <107> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_#61#______
| |
~9~ _~267~
|
~107~
case 1 <61> (若当前结点是根结点,则将其颜色设置为黑色) :
_~61~______
| |
#9# _#267#
|
~107~
result:
_#61#______
| |
#9# _#267#
|
~107~
Inserting 301 -----------------------------------------------------
case 1 <301> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#______
| |
#9# _#267#_
| |
~107~ ~301~
case 2 <301> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#______
| |
#9# _#267#_
| |
~107~ ~301~
result:
_#61#______
| |
#9# _#267#_
| |
~107~ ~301~
Inserting 173 -----------------------------------------------------
case 1 <173> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#___________
| |
#9# ______#267#_
| |
~107~_ ~301~
|
~173~
case 2 <173> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#___________
| |
#9# ______#267#_
| |
~107~_ ~301~
|
~173~
case 3 <173> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_#61#___________
| |
#9# ______#267#_
| |
~107~_ ~301~
|
~173~
case 1 <267> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#___________
| |
#9# ______~267~_
| |
#107#_ #301#
|
~173~
case 2 <267> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#___________
| |
#9# ______~267~_
| |
#107#_ #301#
|
~173~
result:
_#61#___________
| |
#9# ______~267~_
| |
#107#_ #301#
|
~173~
Inserting 129 -----------------------------------------------------
case 1 <129> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#________________
| |
#9# ___________~267~_
| |
#107#______ #301#
|
_~173~
|
~129~
case 2 <129> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#________________
| |
#9# ___________~267~_
| |
#107#______ #301#
|
_~173~
|
~129~
case 3 <129> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_#61#________________
| |
#9# ___________~267~_
| |
#107#______ #301#
|
_~173~
|
~129~
case 4 <129> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
_#61#________________
| |
#9# ___________~267~_
| |
#107#______ #301#
|
_~173~
|
~129~
case 4 handle1: 若当前结点是左子结点,父结点是右子结点,则右旋父结点,下次处理旋转后右子结点:
右旋: 173
_#61#________________
| |
#9# ___________~267~_
| |
#107#_ #301#
|
~129~_
|
~173~
case 5 <173> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
_#61#________________
| |
#9# ___________~267~_
| |
#107#_ #301#
|
~129~_
|
~173~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
_#61#________________
| |
#9# ___________~267~_
| |
~107~_ #301#
|
#129#_
|
~173~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 107
_#61#________________
| |
#9# ______~267~_
| |
_#129#_ #301#
| |
~107~ ~173~
result:
_#61#________________
| |
#9# ______~267~_
| |
_#129#_ #301#
| |
~107~ ~173~
Inserting 232 -----------------------------------------------------
case 1 <232> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_#129#_ #301#
| |
~107~ ~173~_
|
~232~
case 2 <232> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_#129#_ #301#
| |
~107~ ~173~_
|
~232~
case 3 <232> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_#129#_ #301#
| |
~107~ ~173~_
|
~232~
case 1 <129> (若当前结点是根结点,则将其颜色设置为黑色) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_~129~_ #301#
| |
#107# #173#_
|
~232~
case 2 <129> (若该结点的父结点是黑色,则依然有效并返回) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_~129~_ #301#
| |
#107# #173#_
|
~232~
case 3 <129> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_~129~_ #301#
| |
#107# #173#_
|
~232~
case 4 <129> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
_#61#_____________________
| |
#9# ___________~267~_
| |
_~129~_ #301#
| |
#107# #173#_
|
~232~
case 4 handle1: 若当前结点是左子结点,父结点是右子结点,则右旋父结点,下次处理旋转后右子结点:
右旋: 267
_#61#______
| |
#9# _~129~___________
| |
#107# ______~267~_
| |
#173#_ #301#
|
~232~
case 5 <267> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
_#61#______
| |
#9# _~129~___________
| |
#107# ______~267~_
| |
#173#_ #301#
|
~232~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
_~61~______
| |
#9# _#129#___________
| |
#107# ______~267~_
| |
#173#_ #301#
|
~232~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 61
______#129#___________
| |
_~61~_ ______~267~_
| | | |
#9# #107# #173#_ #301#
|
~232~
result:
______#129#___________
| |
_~61~_ ______~267~_
| | | |
#9# #107# #173#_ #301#
|
~232~
Inserting 211 -----------------------------------------------------
case 1 <211> (若当前结点是根结点,则将其颜色设置为黑色) :
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#______ #301#
|
_~232~
|
~211~
case 2 <211> (若该结点的父结点是黑色,则依然有效并返回) :
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#______ #301#
|
_~232~
|
~211~
case 3 <211> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#______ #301#
|
_~232~
|
~211~
case 4 <211> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#______ #301#
|
_~232~
|
~211~
case 4 handle1: 若当前结点是左子结点,父结点是右子结点,则右旋父结点,下次处理旋转后右子结点:
右旋: 232
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#_ #301#
|
~211~_
|
~232~
case 5 <232> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# #173#_ #301#
|
~211~_
|
~232~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
______#129#________________
| |
_~61~_ ___________~267~_
| | | |
#9# #107# ~173~_ #301#
|
#211#_
|
~232~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 173
______#129#________________
| |
_~61~_ ______~267~_
| | | |
#9# #107# _#211#_ #301#
| |
~173~ ~232~
result:
______#129#________________
| |
_~61~_ ______~267~_
| | | |
#9# #107# _#211#_ #301#
| |
~173~ ~232~
Inserting 122 -----------------------------------------------------
case 1 <122> (若当前结点是根结点,则将其颜色设置为黑色) :
___________#129#________________
| |
_~61~_ ______~267~_
| | | |
#9# #107#_ _#211#_ #301#
| | |
~122~ ~173~ ~232~
case 2 <122> (若该结点的父结点是黑色,则依然有效并返回) :
___________#129#________________
| |
_~61~_ ______~267~_
| | | |
#9# #107#_ _#211#_ #301#
| | |
~122~ ~173~ ~232~
result:
___________#129#________________
| |
_~61~_ ______~267~_
| | | |
#9# #107#_ _#211#_ #301#
| | |
~122~ ~173~ ~232~
Inserting 28 -----------------------------------------------------
case 1 <28> (若当前结点是根结点,则将其颜色设置为黑色) :
___________#129#________________
| |
_____~61~_ ______~267~_
| | | |
#9#_ #107#_ _#211#_ #301#
| | | |
~28~ ~122~ ~173~ ~232~
case 2 <28> (若该结点的父结点是黑色,则依然有效并返回) :
___________#129#________________
| |
_____~61~_ ______~267~_
| | | |
#9#_ #107#_ _#211#_ #301#
| | | |
~28~ ~122~ ~173~ ~232~
result:
___________#129#________________
| |
_____~61~_ ______~267~_
| | | |
#9#_ #107#_ _#211#_ #301#
| | | |
~28~ ~122~ ~173~ ~232~
Inserting 82 -----------------------------------------------------
case 1 <82> (若当前结点是根结点,则将其颜色设置为黑色) :
_______________#129#________________
| |
_____~61~_____ ______~267~_
| | | |
#9#_ _#107#_ _#211#_ #301#
| | | | |
~28~ ~82~ ~122~ ~173~ ~232~
case 2 <82> (若该结点的父结点是黑色,则依然有效并返回) :
_______________#129#________________
| |
_____~61~_____ ______~267~_
| | | |
#9#_ _#107#_ _#211#_ #301#
| | | | |
~28~ ~82~ ~122~ ~173~ ~232~
result:
_______________#129#________________
| |
_____~61~_____ ______~267~_
| | | |
#9#_ _#107#_ _#211#_ #301#
| | | | |
~28~ ~82~ ~122~ ~173~ ~232~
Inserting 287 -----------------------------------------------------
case 1 <287> (若当前结点是根结点,则将其颜色设置为黑色) :
_______________#129#________________
| |
_____~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~ ~82~ ~122~ ~173~ ~232~ ~287~
case 2 <287> (若该结点的父结点是黑色,则依然有效并返回) :
_______________#129#________________
| |
_____~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~ ~82~ ~122~ ~173~ ~232~ ~287~
result:
_______________#129#________________
| |
_____~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~ ~82~ ~122~ ~173~ ~232~ ~287~
Inserting 54 -----------------------------------------------------
case 1 <54> (若当前结点是根结点,则将其颜色设置为黑色) :
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 2 <54> (若该结点的父结点是黑色,则依然有效并返回) :
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 3 <54> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 4 <54> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 5 <54> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
#9#_ _#107#_ _#211#_ _#301#
| | | | | |
~28~_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
_______________#129#________________
| |
_________~61~_____ ______~267~______
| | | |
~9~_ _#107#_ _#211#_ _#301#
| | | | | |
#28#_ ~82~ ~122~ ~173~ ~232~ ~287~
|
~54~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 9
_______________#129#________________
| |
_____~61~_____ ______~267~______
| | | |
_#28#_ _#107#_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ ~82~ ~122~ ~173~ ~232~ ~287~
result:
_______________#129#________________
| |
_____~61~_____ ______~267~______
| | | |
_#28#_ _#107#_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ ~82~ ~122~ ~173~ ~232~ ~287~
Inserting 95 -----------------------------------------------------
case 1 <95> (若当前结点是根结点,则将其颜色设置为黑色) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____#107#_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ ~82~_ ~122~ ~173~ ~232~ ~287~
|
~95~
case 2 <95> (若该结点的父结点是黑色,则依然有效并返回) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____#107#_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ ~82~_ ~122~ ~173~ ~232~ ~287~
|
~95~
case 3 <95> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____#107#_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ ~82~_ ~122~ ~173~ ~232~ ~287~
|
~95~
case 1 <107> (若当前结点是根结点,则将其颜色设置为黑色) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____~107~_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ #122# ~173~ ~232~ ~287~
|
~95~
case 2 <107> (若该结点的父结点是黑色,则依然有效并返回) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____~107~_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ #122# ~173~ ~232~ ~287~
|
~95~
case 3 <107> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
___________________#129#________________
| |
_____~61~_________ ______~267~______
| | | |
_#28#_ _____~107~_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ #122# ~173~ ~232~ ~287~
|
~95~
case 1 <129> (若当前结点是根结点,则将其颜色设置为黑色) :
___________________~129~________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ #122# ~173~ ~232~ ~287~
|
~95~
result:
___________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~_ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ #122# ~173~ ~232~ ~287~
|
~95~
Inserting 116 -----------------------------------------------------
case 1 <116> (若当前结点是根结点,则将其颜色设置为黑色) :
________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~287~
| |
~95~ ~116~
case 2 <116> (若该结点的父结点是黑色,则依然有效并返回) :
________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~287~
| |
~95~ ~116~
result:
________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~287~
| |
~95~ ~116~
Inserting 281 -----------------------------------------------------
case 1 <281> (若当前结点是根结点,则将其颜色设置为黑色) :
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _~287~
| | |
~95~ ~116~ ~281~
case 2 <281> (若该结点的父结点是黑色,则依然有效并返回) :
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _~287~
| | |
~95~ ~116~ ~281~
case 3 <281> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _~287~
| | |
~95~ ~116~ ~281~
case 4 <281> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _~287~
| | |
~95~ ~116~ ~281~
case 5 <281> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _#301#
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _~287~
| | |
~95~ ~116~ ~281~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
________________________#129#________________
| |
_____#61#_________ ______#267#___________
| | | |
_#28#_ _____~107~______ _#211#_ _~301~
| | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ _#287#
| | |
~95~ ~116~ ~281~
case 5 handle2: 若当前结点和父结点是左子结点,则右旋祖父结点:
右旋: 301
________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~281~ ~301~
| |
~95~ ~116~
result:
________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~281~ ~301~
| |
~95~ ~116~
Inserting 93 -----------------------------------------------------
case 1 <93> (若当前结点是根结点,则将其颜色设置为黑色) :
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_____ _#122# ~173~ ~232~ ~281~ ~301~
| |
_~95~ ~116~
|
~93~
case 2 <93> (若该结点的父结点是黑色,则依然有效并返回) :
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_____ _#122# ~173~ ~232~ ~281~ ~301~
| |
_~95~ ~116~
|
~93~
case 3 <93> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_____ _#122# ~173~ ~232~ ~281~ ~301~
| |
_~95~ ~116~
|
~93~
case 4 <93> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_____ _#122# ~173~ ~232~ ~281~ ~301~
| |
_~95~ ~116~
|
~93~
case 4 handle1: 若当前结点是左子结点,父结点是右子结点,则右旋父结点,下次处理旋转后右子结点:
右旋: 95
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~281~ ~301~
| |
~93~_ ~116~
|
~95~
case 5 <95> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _#122# ~173~ ~232~ ~281~ ~301~
| |
~93~_ ~116~
|
~95~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _________~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ ~82~_ _#122# ~173~ ~232~ ~281~ ~301~
| |
#93#_ ~116~
|
~95~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 82
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~ ~95~ ~116~
result:
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~ ~95~ ~116~
Inserting 122 -----------------------------------------------------
result:
____________________________#129#________________
| |
_____#61#_____________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~ ~95~ ~116~
Inserting 90 -----------------------------------------------------
case 1 <90> (若当前结点是根结点,则将其颜色设置为黑色) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~_ ~95~ ~116~
|
~90~
case 2 <90> (若该结点的父结点是黑色,则依然有效并返回) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~_ ~95~ ~116~
|
~90~
case 3 <90> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____#93#_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
~82~_ ~95~ ~116~
|
~90~
case 1 <93> (若当前结点是根结点,则将其颜色设置为黑色) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____~93~_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
#82#_ #95# ~116~
|
~90~
case 2 <93> (若该结点的父结点是黑色,则依然有效并返回) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____~93~_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
#82#_ #95# ~116~
|
~90~
case 3 <93> (若结点的叔父结点(和父亲)是红色,则将叔父和父亲都变成黑色,将祖父变成红色并转到case 1) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____~93~_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
#82#_ #95# ~116~
|
~90~
case 4 <93> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置不同:) :
________________________________#129#________________
| |
_____#61#_________________ ______#267#______
| | | |
_#28#_ _____~107~______ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ _____~93~_ _#122# ~173~ ~232~ ~281~ ~301~
| | |
#82#_ #95# ~116~
|
~90~
case 4 handle1: 若当前结点是左子结点,父结点是右子结点,则右旋父结点,下次处理旋转后右子结点:
右旋: 107
________________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~93~_____ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _~107~______ ~173~ ~232~ ~281~ ~301~
| | |
~90~ #95# _#122#
|
~116~
case 5 <107> (若父亲是红色,叔父是黑色,当前结点和父结点的左右位置相同: ) :
________________________________#129#________________
| |
_____#61#_________ ______#267#______
| | | |
_#28#_ _____~93~_____ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _~107~______ ~173~ ~232~ ~281~ ~301~
| | |
~90~ #95# _#122#
|
~116~
case 5 handle1: 将父结点设置为黑色,祖父设为红色:
________________________________#129#________________
| |
_____~61~_________ ______#267#______
| | | |
_#28#_ _____#93#_____ _#211#_ _#287#_
| | | | | | | |
~9~ ~54~ #82#_ _~107~______ ~173~ ~232~ ~281~ ~301~
| | |
~90~ #95# _#122#
|
~116~
case 5 handle2: 若当前结点和父结点是右子结点,则左旋祖父结点:
左旋: 61
____________________#129#________________
| |
_________#93#_____ ______#267#______
| | | |
_____~61~_ _~107~______ _#211#_ _#287#_
| | | | | | | |
_#28#_ #82#_ #95# _#122# ~173~ ~232~ ~281~ ~301~
| | | |
~9~ ~54~ ~90~ ~116~
result:
____________________#129#________________
| |
_________#93#_____ ______#267#______
| | | |
_____~61~_ _~107~______ _#211#_ _#287#_
| | | | | | | |
_#28#_ #82#_ #95# _#122# ~173~ ~232~ ~281~ ~301~
| | | |
~9~ ~54~ ~90~ ~116~