8 x5 ~3 d {6 E& D$ P8 I N1" j) q: H! i5 s* R9 @+ [
2 4 m# G/ z! T$ L- g h+ Q" r, ?2 r38 s7 C: V+ K3 F$ e
4 $ X- U; W! I; G. G) a5 * v" [9 f9 \* C A! t6+ e/ x% `1 a: \+ s
7+ W- X: [: o( h* [' A2 F5 M
8: L& E6 X/ f; R. v2 `! P; c( ~6 h
98 O; H: T- K) L) C. Q
107 T0 _& o/ ?& p
11) Q6 k& m: {. E: b: s7 F
126 \4 ~) b- a! E' O
13) M: ~3 w4 U1 C' U3 @, X/ B( H
14 ' Y8 K5 b- Y" Z C/ d1 m! H15 # J: ?3 Y( C! P+ P! x2 O' k164 M7 C* R4 r! Q
17 3 V; L9 y6 P/ T18 4 ^5 U; D$ m8 q0 V4 J/ j红黑树插入实现- u+ U0 |# g$ ?$ c. c6 }6 A/ H& P
首先我们知道插入的节点的颜色是红色,因此它不会影响插入路径上黑色节点的个数.而当插入节点的父亲节点的颜色为黑色时,此时我们其实无须作任何处理(因为插入的节点是红色唯一可能造成的影响就是两个红色节点相连),如图 7 g0 ?) U( j' O# P% X 3 O! l4 p/ S; |+ \因此我们需要考虑的是待插入节点的父亲节点的颜色为红色.这种情况下待插入节点的爷爷节点一定是黑色,此时我们需要考虑如何将两个连续的红色节点分开且不影响红黑树本身,此时我们需要考虑父亲节点的兄弟节点(叔叔节点)的颜色. # Q$ E' G, B- |1 `: u- \+ k如果叔叔节点的颜色为红色,那么此时只能将父亲节点和叔叔节点的颜色变为黑色,然后爷爷节点的颜色变为红色,然后从爷爷节点开始继续向上遍历调整红黑树的结构. 0 H: w8 C5 d- o( ]- t) ]- I& w' B3 b; i3 k2 T* D
如果叔叔节点的颜色为黑色,那么此时我们只需要通过旋转即可分开连续的两个红色节点,具体的旋转操作请参考高级数据结构——AVL树/ h# o" G/ o% x Y6 F
此时分为两种情况,第一种情况是待插入节点是父亲节点的左子节点,此时只需右旋爷爷节点,然后交换爷爷节点和父亲节点的颜色2 |+ ^% i; F% v
: N4 b7 m3 O# N! u4 ~第二种情况是待插入节点是父亲节点的右子节点,此时需要先将第二种情况转化为第一种情况,即左旋父亲节点并交换父亲节点和待插入节点的指针,然后和第一种情况的处理方式类似 2 i0 n$ n$ x& I8 y" e0 L3 p# y6 i ' D9 \4 { g# z2 B0 j, A . R5 N7 \6 c# o( d0 c0 P7 {5 d以上讨论的情况是父亲节点是爷爷节点的左子节点,而当父亲节点是爷爷节点的右子节点时,实现逻辑是一致的,就是将左右对调即可.3 C, Q" m+ A6 @- {4 k
在对红黑树的结构调整完后,需要注意将根节点的颜色设置为黑色,因为红黑树的结构调整的过程中很有可能会改动到根节点( R4 \% c8 t5 P. b, r
- |8 Y" y7 |9 R6 V* u
public class RBTree { / a; F& G# P" ~! U static class RBTreeNode { A v' P! R5 H7 Z& H/ t! t" W
public int val; 4 G1 q, @) i. _, Y" ]' w public RBTreeNode left; & u4 o* B W3 Y% a public RBTreeNode right;6 ]- u ]/ }; _' S, ^/ {) r
public RBTreeNode parent;9 q( ]) ?! w& y
public COLOR color;# D; a, z: I5 o. U. p- ^
5 C! K* U, q' S) k public RBTreeNode(int val) {( q, U: K: ?2 i' p& @
this.val = val;' n9 [+ }: R& z+ i' q+ [# V
//默认插入的节点的颜色是红色,如果是黑色会造成插入的麻烦:( _) R5 R0 U' W: q9 }/ z- ~/ p
//由于要满足任意一条路径上的黑色节点的个数相同,所以要在其他路径上新添加一些没有意义的黑色节点 5 {1 \& H/ |% s //而插入的节点是红色节点,我们只需要调节该路径上节点的颜色" V& t) B$ |$ u+ z C( A: q' [
this.color = COLOR.RED; i; c; p" W8 Y- B t4 P } 1 r4 p: `2 ^% v5 D; j8 [" ] }! l" w; A; z9 F$ |1 e
" F$ k( W! T* g: g- _( R1 r o public RBTreeNode root; % M) F* R( Y. _0 Z% W2 y# y0 z ^# T" v% [% C; D
public boolean insert(int val) {0 H& {( ?) d5 f. X7 x8 I! `
if(root == null){ , M3 V* Y+ c) c: Q7 e // 插入第一个节点时直接给根节点赋值即可 $ d( S! E' f& }* f$ w root = new RBTreeNode(val); 3 C1 h/ l% z& q7 Q# j& G root.color = COLOR.BLACK;) a. b2 D8 p; I2 N
return true;2 ~. C3 I7 O* i' A w& t# `
}3 u) _+ \- G7 | T1 ?1 ], w" f* y
RBTreeNode node = new RBTreeNode(val);! s3 | J4 z$ o+ I% e0 I1 P$ Z
RBTreeNode cur = root;7 F, s: r1 ^ S' N% M; R6 ~
RBTreeNode p = null;2 J; ]- L( \6 m0 ?: D1 U- b
// 寻找待插入节点的位置) N8 o* A/ D' B+ [/ B: m
while (cur != null) {8 Z# B& d- }6 d
if (cur.val < val) { 5 s% q$ ?, v/ |+ Z+ z p = cur; % X, j/ d+ ~5 r6 B7 t; i$ I2 j8 ]* o cur = cur.right;, ^1 v: U& z2 s
} else if (cur.val == val) { j% L) @4 F( W9 S0 _3 S) e return false;5 i5 x; c; B$ H1 C# `( I- Q
} else { 1 |$ l! r8 e8 q" L" G- g3 b( q+ o; U; r p = cur; t! U% f$ b& r, d1 W cur = cur.left; $ k/ r5 |4 C& W9 \) t# X; R: r }) _, k5 d5 Y; p
}5 P# B. F3 |, n( f4 V1 W
if (p.val < val) {% z/ i6 Y4 `" P3 d1 {7 q* P
p.right = node;) `6 \1 U) P& j# ^) g
} else if (p.val > val) { 9 A9 H" i% W' O* A P p.left = node;4 h& {2 T' ?& n S2 E
}2 k& G D" {( L. V9 p" Z
node.parent = p; # K; h7 A. B) {, L( Z5 H1 K cur = node;1 s4 Z( e6 ?- P" q8 p/ o
// 调整红黑树结构 0 o/ d8 m2 s6 {- u7 }8 y/ j1 P5 W while (p != null && p.color == COLOR.RED) {0 i2 h1 z$ }' p7 E2 I& ?
RBTreeNode pp = p.parent;7 [0 [% k$ C( C' U+ ?* N$ C
if (pp.left == p) {% X4 k9 @* k( ^2 {( e8 P4 P& R V! u
RBTreeNode uncle = pp.right;7 w P, h# O& l4 P" K; U0 }
// 叔叔节点为红色5 C k& s7 X$ R3 t
if (uncle != null && uncle.color == COLOR.RED) { # R7 z& a6 s, F, H, `4 i0 D p.color = COLOR.BLACK; 7 P! M9 ~2 x" N; s2 v' Z2 ^: n& [1 o8 } uncle.color = COLOR.BLACK;$ w, B1 `3 G+ ?; s
pp.color = COLOR.RED; : G! G, T* R5 E6 f5 X4 D cur = pp; r; V7 J8 I! }2 y" A p = cur.parent; $ p; n/ N: r* C' P& O S } else {6 Q4 c* l2 v& J8 t
// 叔叔节点不存在或为黑色7 Q" ]: x5 v% l' f
if (cur == p.right) { 0 b: S% ?# `0 r' Q" s rotateLeft(p);5 d: G7 P( ~. u# n9 s2 m( l9 m
RBTreeNode tmp = cur; {" ^0 l/ ~$ S. E% | cur = p; : R2 i( V2 O, n* X. \7 s/ t p = tmp; ; ~1 B% ?/ @6 N } ; S4 t4 P" ?- ~6 Y% o0 X rotateRight(pp);# p$ `; o( r0 ?& H$ G' [) r
pp.color = COLOR.RED; : o$ e+ J& R+ ^: B, `1 ~9 n5 P( t p.color = COLOR.BLACK; $ U" x: N3 Q, p3 C& P* c1 b7 ^4 c7 m' L }: J {, \$ ?! d: q% p5 z9 W. j
} else {8 b# H6 o: w% ?1 o
RBTreeNode uncle = pp.left;8 s+ m. E# ^. P: S5 ~! E6 R
if (uncle != null && uncle.color == COLOR.RED) {8 [- j) c& w+ w: t
p.color = COLOR.BLACK; 9 ^/ k1 v! b7 A4 m$ Z uncle.color = COLOR.BLACK;8 D7 x0 D' w: \% w6 s
pp.color = COLOR.RED; , j# m% E/ ~. D. O/ p; ]: ? cur = pp; ' {% N+ D& [2 ?3 b1 P" K2 B+ w p = cur.parent;' L# `0 u4 r3 N2 Q$ Y( @
} else {) d" w l* }* _/ [( K
if (cur == p.left) { ) m2 y! r+ V6 ~. {( m1 \) b( K rotateRight(p);$ c* U* `+ j, \" E& n0 K0 U% r
RBTreeNode tmp = cur; . F0 `! Y1 a* Z8 m: U3 N cur = p;5 J/ d3 w+ k. C0 ]/ U
p = tmp;4 M# b; X2 ?5 F9 O* l8 \* x- c
} $ d3 j( l0 D, d, t rotateLeft(pp); / `+ Y# w8 q1 H6 n pp.color = COLOR.RED;% E& O+ [9 i& j. M& M" [1 n3 o- _! L
p.color = COLOR.BLACK; % l" O, d- V& e$ R9 P$ P } 6 H3 S) V' `5 S8 q } + p/ Y3 S$ q0 [# r4 d8 ] }; ]/ R2 P- l2 Z3 V
//这个必须加,因为在插入的过程中,红黑树的根是在变化的,而变化则导致根节点的颜色得不到保证 8 G( [1 K/ {: n8 E //尤其是遇见第一种青光将pp的颜色设置为红.7 L3 R7 L9 X& I Y$ E$ Q
root.color = COLOR.BLACK;! q) W V9 E2 X2 v9 Y* s: c4 j' m4 Y v
return true;/ W( H$ z4 U& Z* }8 }0 N# l
}" r3 `$ \* }9 @" \. f: ]5 D
4 o! l9 c7 e- ?9 B
private void rotateRight(RBTreeNode p) { 1 z, u, S* c: `4 ^/ {9 D$ w# z% O4 o( d/ r RBTreeNode pp = p.parent; $ k, ?6 t2 u. `& I/ ?; _# o RBTreeNode newRoot = p.left;& v! Y8 ^ ~% _( O
p.left = newRoot.right;5 F4 n" B9 W; G# {4 e& ]& Y& W$ T8 a
if (p.left != null) {6 w/ i. h$ x$ @
p.left.parent = p;. a, x: |" N0 P
} - f8 N/ L/ P2 B# V! e: [ newRoot.right = p; 5 N3 o' B% u" s) V9 W p.parent = newRoot; 1 a& o4 T5 a% L2 R$ ~ if (pp != null) {: \) |& |$ T, y; ~# Z
if (pp.left == p) { # D& j! g# G4 k9 { pp.left = newRoot;5 L- _" O- D! {1 B
newRoot.parent = pp;; R9 p- L4 c) ]9 `# X& }6 V7 Q1 K
} else if (pp.right == p) { B( n& A" I9 D% h
pp.right = newRoot; * s5 l. P0 } y5 V: Q newRoot.parent = pp;4 G6 T& |) x8 O/ X# G
}; _1 s. M0 G) r9 [
} else { 4 |' ^* y- q$ [: t3 P- F( W6 g newRoot.parent = null;! v9 I1 K! t4 V+ d: i: u
root = newRoot; 4 i8 b; M& ]- |6 z. C9 ~% m } 1 n4 c* V! @1 ~- I' g }5 d( M! y! U& E# d, {
2 B" I F) a" h7 u; K
private void rotateLeft(RBTreeNode p) {2 I; O2 M0 @' _: k* K+ s1 v
RBTreeNode pp = p.parent; * r8 T4 L3 P! A8 B9 o m RBTreeNode subR = p.right; + m* o) ?! d) a9 [" {% R RBTreeNode subRL = subR.left; # y n9 C8 T# P# K7 g' Q. k- I p.right = subRL; ) U( E; |6 r& T& | if (subRL != null) {/ v& s9 b- a' u" p3 j5 q
subRL.parent = p; " R0 c, D% b+ G$ m T: G6 H; D+ G } $ h+ e/ ^; \7 c2 p( U3 }( L+ c/ J8 y subR.left = p;6 L: q) O- q6 U8 a8 x/ m# [$ j
p.parent = subR; , y( ?% d I4 r$ X- J( H) H% ` if (pp != null) {: _. u" X+ [9 w+ l8 V
if (pp.left == p) {8 V. F- n7 V/ Q* D
pp.left = subR;3 Y! N; f; e% D: d2 K# P
subR.parent = pp;# t" D4 K' a. _+ @) O) v* U
} else if (pp.right == p) {; y' m) a9 v; x# y7 d
pp.right = subR; 2 V2 v2 K7 s" n9 v! \2 I9 R subR.parent = pp;2 ^! e* n5 v# M" g1 k& ~
} ! d& f/ H5 ]. |/ A6 I y! { } else { : r) o' c' Z5 R4 E& n4 A0 ] subR.parent = null;+ v& a; ^: y" s" W H e3 \
root = subR;6 O; V6 l* A9 `: F, e
} # [/ ~0 |$ U& k) F } 5 k: x0 k K4 e$ T9 A7 r - y7 p* J; X: V+ ? m. t* d% t - t0 {8 m" N0 A 0 M# ^2 p# ~1 j' S# M7 C8 ?% `7 P2 X+ ?7 k& @# v
18 M' I/ t C) n/ R6 P/ c" J' }+ [
28 `( s% w6 ]* g. n+ W8 C7 ?
3 2 w3 J- a+ h& a! y$ s4 C4; o4 @+ }) {% Y$ u1 @2 b
5% Z! h* X T- m2 ]3 p# x: `
68 Z1 q/ H1 A7 P3 l
7' G. \0 Y" J+ N0 y
8 / X; d, j% c$ }5 N' X4 Q9 * M& ^9 q2 g$ B) M" N4 D" z+ L10& v; X& a" _1 H0 c2 {, k F
11 2 T# ^* ~" f3 |- q' b12 9 n3 w; p8 w! k0 Q1 r13% g) H. r! ]* M: i1 F4 r1 o/ C
14 1 k# Q1 [' K3 B0 Q# D15: k. k+ k" K$ w7 i: D/ h* o# P
16 / o' t6 _ A8 Z) i1 n17. @) A4 u2 j' s9 Y# I( [
18; c4 |$ o4 q7 _2 m( X9 O$ S
19 , `3 F8 g, r) n% t) x203 |* d0 @. U+ R3 J3 ?/ a
21" S6 G8 v7 O9 X( t m
22 9 n5 a% N( U% v4 w% V q8 C Y8 B23 ) c( i% ^% w2 M* P2 B4 D5 f24 : i" A4 z) n6 x" ^5 w& s257 ]1 p9 B4 X# a, L4 q
26 2 [/ \/ W$ ~2 U9 _7 |6 K3 m27 0 r) D9 K& l0 u5 R' A4 a28/ k& s0 m) x9 |, b
29: i0 S2 P5 @* X' ^$ |
30. r8 X, S- L6 Z: `* D/ n
31 ! Y I3 w( B% T1 ^7 R& a+ ]9 M321 ~2 w$ S' E3 t2 M
33 7 C1 d5 t, l- D9 C* \7 i2 E6 C34 + O! j, i/ A% y" n! J. x6 U* w7 v35. y7 S4 a# T8 A% Y0 P
36 3 U$ B( Y6 g% w- j37 ' Z( Y' B) ?& h; q38 8 B5 Y' U5 e4 _39 6 G7 a# [: w7 q$ e40* }( {9 Q# _% P( x# H: X
41 7 J# @; w7 `( H0 G& h2 ^/ P W42 . M0 `, ?( ?1 b" R431 r9 @; R9 D/ ^+ a3 u
44 8 i4 D7 Y0 L4 B8 r9 ?) f" J45: g K1 d* v' E! c% F* \& j
46; B3 t: }: Z- d. |# L7 }
47& [, Q8 v5 A3 s. u) T. `0 b
48, [2 C2 |* e9 o# w
492 D; n2 r3 Z; i& ~9 W
50 6 a0 B/ B! j$ E1 N51 : s: V. O3 X+ Y/ ^: }52! `* q/ r) z! T1 n
537 A" }& ?3 N7 D& p
548 `. \8 O& J" z2 c8 D' R. x
55 # q3 h [% V; g5 C4 _- m/ ~' E56 # |( g! i" k5 q4 l) O6 ]575 @3 T6 ]9 m! M- F0 f' a
58/ m X* e) M6 v% l4 \" R6 U6 `: i1 n
59 + j; Y7 r+ J$ _0 k60+ d2 m( o# q6 V* E# \/ G# L0 z4 }
61 - S( F: D5 @1 k) C1 x* G C" W8 e626 @" n5 k+ C0 L1 L' @
630 B2 S, {# a4 h8 T0 e5 E6 r0 p
64 $ J2 N* s8 d( S0 x) A* B65; Q, |! g0 j8 T$ F* h. M
66/ r0 a0 Q8 D1 k; s' g1 N
67 " W$ D8 V8 @ J" y6 F' x1 ^$ G68 + |$ N4 D, |8 G9 J6 h* r# o69; p8 B/ k0 t/ J% q* S- s
70, @0 U- R A1 T, f6 p# h0 H6 O
718 ]+ r w9 M$ S4 R: I; v6 V
72 5 C8 {/ c- ]9 l: O! B2 R. e1 @% s737 Q- U' b+ e( `5 T; z" l
74 9 ^* u" R" V9 ?- o3 \* T/ c75) p, I d* l" r+ {. p
76 - ?, [- ]5 Z2 F) c77: v% O; k W9 ]+ J
78 * V" G1 ?, P8 T! S79 & V( |. e' `* R/ Z# ^80 9 L' x# B& {1 I+ [0 x- {- O' P81 4 Y& \# o5 z# {/ t5 s6 b820 e& \5 Q, O. z
83 ( ^7 J- c7 {0 @% t84 " o- g# v3 c- B, o6 O: `$ S85- s/ A* }0 N& \1 p+ s
86 & T& r3 I+ D% A( c87 3 E" I" A- @! v* ]+ k% l88 - V# x, L0 ]' G& g9 u) m1 w$ l$ ?& v& D893 A4 H9 u( p, B( t! b: O
90/ ]; d$ L2 p9 `( B. J D
918 g3 W0 s# M4 ?) k. T: ~
92 , M( B/ `/ X& w% }" T" m+ {93$ T4 d1 n1 q# i* L- c! a. Y
94 1 W$ v# a; k+ ]# D95 9 D* Z& l7 l1 z! M, N7 C9 L$ B96: ^# a' e: ?5 O. a% A
97, Z4 Y9 L5 F& F
98. U" p: s, N$ ]8 `
99 8 P1 M4 ~1 u" A8 R" z9 ]) O100. S+ A0 v0 z+ k. N9 O
101! w, U: T5 ?$ c1 b! }
102 / ]- t4 H) e9 f2 T! ]3 e6 ]7 N103 5 _, I" J! V, r104' n: A/ g' n J0 {3 U( z% r7 f, M
105" V8 W9 S; t; s
106% H5 n( V: W; _" n
107 ' J4 ^. y- v, u7 z% K108! w( i4 E- W* @" `9 a2 `! e
109) Q5 c j6 ~6 B6 k( U
110 + N8 I) h( U, l9 u" j111 ) r" a9 [# E0 h( ?112- K' G8 _" h1 d/ `0 @" |
113 % Q% m- r6 i# f114 4 C2 n8 I- ^9 ^/ G115 2 Q! t n6 m; t116. W3 Z9 F6 i& l e( G* o) [4 E9 z' @
117 1 N/ V6 ?+ X( c5 l% V1181 I% m2 x9 y* T: @8 `6 I7 S6 [+ F
119 . Z8 d/ a2 {2 p; o4 u# P/ a6 b2 j120 4 S/ Y( d; b e( F1216 z4 R" Z" s5 }- q: \8 [. I3 w7 P
122 0 J, G, o/ A0 P123+ D$ l. B4 A/ T8 f1 B, Y& X
124* H6 j0 g2 E. q' j' j; ^" C5 B2 X
125 1 u/ N* `, l' I( Q$ U126% D; w; D1 o7 K( {0 P! _
127- T( G" o. c6 S4 ]5 z
128 " u L4 q3 L7 d1 Z9 e0 M129$ F3 l$ J, F* ?3 x. {% n& x% e
130 9 N. o' o3 i7 J' B7 g131 : _6 N/ c0 U+ Q* Q; t132 9 _2 O# o @ c4 a3 A' W6 x133 - }. D6 ^4 L9 j3 w& K3 K3 M134 ' w1 K% u- k! g+ E) o4 X" L135 ' }1 a/ X! y- W136 - c) g) z. _- O3 L* R8 [137 ( B9 ^- S4 w! }- z6 x138# `2 Z s O; _( P' b
139 3 B: r5 B3 H$ F/ e5 g# o( j7 l, W140& t' B. Q0 k9 E( z3 u
1417 t; e' a( Y6 i; F
142 ; p7 d( [: i8 ] x, E$ ?1 l1438 @: v3 E$ h: d1 \/ L- k7 y, D3 m9 c
144/ @$ T# P0 H+ K7 E1 }) J! E* E
1454 x6 Y/ I7 T9 Y% A. l" R
146 , |; \5 T1 F, B1 H% c147 # r6 l9 i# S5 S. V' h1 G9 M148 ) n( ^) H, ^/ H9 `+ X红黑树删除实现( g+ I5 A% w/ v3 P& k) k
红黑树的删除的主要思路和二叉搜索树的删除思路相似,都是先找到待删除的节点,然后通过找该节点的前驱节点或后继节点来找到替罪羊节点,然后删除替罪羊节点,将替罪羊节点的值赋给待删除节点. ; r7 b8 n1 B! R% G1 F因此我们主要关心的是删除红黑树的叶子节点时会对红黑树的结构造成什么影响.首先如果删除的叶子节点是红色,那么很显然直接删除掉即可,因为红色节点的去除不会影响该路径下黑色节点的个数.如图 : a/ [4 e8 H7 B, X/ P4 ? e$ u而要删除的叶子节点是黑色时,由于该路径下黑色节点的个数减少,所以需要对红黑树进行调整. 0 N( x0 b8 a( e# t: @6 F首先我们要考虑的是尽可能的减少调整红黑树的结构,因此我们首先应该调整的是以待删除节点的父亲节点为根节点的子树的结构.首先规定待删除节点的父亲为父亲节点,其相邻兄弟节点为兄弟节点,兄弟的孩子节点为侄子节点,以父亲节点为根节点的子树称为p树3 {/ A" b: d1 W ?1 I# K8 I: J& j
p树的节点情况大致可以分为5种 2 i/ E5 U; x; `- ] J / Y' J1 n& F+ Y* K% [父亲节点为红色节点,兄弟节点和侄子节点为黑色节点(或为null)# q/ \" }2 _) z! p2 K2 ^: Q
这种情况下删除节点后删除节点所在路径上黑色节点个数-1,因此我们可以将父亲节点和兄弟节点的颜色对换., p8 O. Y1 S9 |* }" _, h
* L/ [7 D C2 |4 C! U# X f, G3 Y
父亲节点,兄弟节点和侄子节点均为黑色(或为null) R* e$ o; @, u5 r. C
这种情况下只需要将兄弟节点的颜色置位红色即可,然后p树的所有路径下黑色节点个数均少1个,因此以父亲节点为基础向上继续调整 ) Y. Y& B% F5 ]( f, V. g% l# v2 A+ E0 D& H$ B9 T
兄弟节点为红色6 |" Q9 y5 i5 V
这种情况下父亲节点和侄子节点的颜色均为黑色(不允许两个连续的红色节点出现).此时删除节点后,该路径下黑色节点个数-1,此时我们将p树左旋,并交换父亲节点和兄弟节点的颜色,此时p树就变成了第1种情况& y! T/ a7 C2 W3 ]
( e0 A( X" a) [) t5 z# Q兄弟节点为黑色,远侄子节点为红色 ( D2 m) r5 [8 _6 `1 J" Z此时我们可以想到将远侄子节点移动到待删除一侧的路径上并置为黑色.所以首先左旋p树,将父亲节点和兄弟节点颜色对换,然后将远侄子节点的颜色置位黑色0 n- }3 y! Y( V& ^( K0 D6 A
2 i2 W$ ?; V" k2 r `
8 c3 U' ?( k5 @$ K- m
兄弟节点为黑色,近侄子节点为红色,远侄子节点为黑色& n$ f; L/ H2 S0 d- ^+ q$ @' E
这种情况和第4种情况类似,因此我们考虑先将第5种情况转换成第4种情况,然后按照第4种情况进行处理.所以首先对兄弟节点右旋,然后交换兄弟节点和近侄子节点的颜色变成第4种情况 * Q" F5 d$ N! u) E2 s综上我们已经讨论了删除节点为父亲节点的左子节点时的所有情况,而当删除节点为父亲节点的右子节点时,只需要将left和right对调即可 ! r; `# V, d# Q# @和二叉搜索树的删除节点一样,我们首先需要找到替罪羊节点,然后将替罪羊节点的值赋给待删除节点.(寻找替罪羊节点可以参考高级数据结构——AVL树)然后以替罪羊节点为待删除节点进行红黑树结构的调整.- w7 b2 x' Z h! B" X+ D4 O
* ^3 ?" n" M7 B; x public int remove(int val){( Z4 p& C% Y$ W+ }
RBTreeNode replaced = getNode(val); * x1 ~' h* t: D$ x if(replaced == null){8 I \, c7 p9 s# S# o
throw new RuntimeException("没有要删除的节点");2 u4 P \- P4 L2 D9 [
} $ G* t9 y$ @* z- a: u RBTreeNode removed = replaced; . n: R8 S! }" f( p if(removed.left != null && removed.right != null){3 M# K; w. R, t+ w' }
removed = getNextNode(removed); ' {. I2 H- t3 ~5 E }' k( V4 q" }; b* A" N8 m
RBTreeNode moved; ' G3 W, [" X: B! i& H RBTreeNode parent = removed.parent;% x. o, \ Q5 k$ m. }+ {4 B% v. n
if(removed.left != null){ % ?, v: t. i' ^1 U& Z5 Y moved = removed.left;* F$ t$ t9 @9 ~) \$ Q9 D( V8 [
}else{ $ l% g* A* I" Y8 l6 c( B, X* y) r: w moved = removed.right;1 S; ]) [' t+ g3 v0 F S
}1 L& o2 J0 k$ B0 S$ P
if(moved != null){ 2 T6 O2 @0 h( m } moved.parent = parent;, n- A$ j' s& Q( t' e
} * o8 d# U4 a9 O& j+ E! w1 T if(parent.left == removed){ % Y. f) T- a7 h8 Z5 X2 f6 j parent.left = moved; 8 Z( h c( @, u6 Z7 Z }else{6 d. z7 S1 Q9 a- {0 d
parent.right = moved;( j, z* z$ E" y* l( u: e, d6 ^4 y N
} 7 w7 A2 D& ]. x3 Z* w( f int oldVal = replaced.val; ' N& Q) z9 w+ M! c2 B- S if(removed.val != replaced.val){ 4 ^. d i1 [4 V9 p replaced.val = removed.val;% ]) t6 O6 Z6 R; c G/ J
}+ r6 }$ U; \3 K+ u
adjustStructure(parent,moved,removed.color);. m- \- J$ n- Z
root.color = COLOR.BLACK; * B7 y0 T$ H3 u0 F/ b9 [ return replaced.val;3 K2 L7 D* T7 D) b. w
, g+ U+ l" @' a9 Z }/ o3 T: u e8 ]2 S
private void adjustStructure(RBTreeNode parent,RBTreeNode removed,COLOR color){2 f' O/ ^* C1 U6 V8 X
RBTreeNode uncle;% H4 g3 O# Z3 \) R- q6 O
do {% t7 ^% f3 C! @0 Q5 G
if(parent.left == removed){ 5 c( k( F' C& ^7 P2 A$ \; y if(color == COLOR.BLACK){ ; U; t8 d" c# ^4 W `+ F( o4 A2 z0 U uncle = parent.right;4 G( q5 t+ M# w1 g
RBTreeNode near = null;1 d& J& ?9 e; G, v
RBTreeNode far = null; % |, D0 ], q8 f/ I if(uncle != null){ 6 A' {4 Z0 z0 e near = uncle.left; - Q# h2 J s! ?9 E. N far = uncle.right; , p" n. z! X) l& C }! \% j7 q$ h4 v
if (parent.color == COLOR.RED && (first(uncle)) && first(near) && first(far)) {! w- n f. S" {, V
// 1.父亲为红,兄弟和侄子为黑! B* i$ T" M+ M0 t3 ^6 v. d! J( h* O
if(uncle != null) {! A- B5 x& F% d4 o/ g5 s
uncle.color = COLOR.RED; ) y) ^( h$ t7 S/ C/ b } 1 V; V) P0 J, u; f2 ~: G/ l parent.color = COLOR.BLACK; - b( Z; X0 Z" g4 z6 Q2 n break; . P# ~# X7 r& h& \9 L % W% _+ s$ n- B( k/ z$ _ _! P } else if (first(parent) && first(uncle) && first(near) && first(far)) { M% L0 i7 K7 w4 t5 _4 M // 2.父亲,兄弟和侄子都为黑色% c, q( V! U: G5 \0 U* y
if(uncle != null){2 A/ d& m& {/ E* O! o
uncle.color = COLOR.RED; J! O* x& G" ` b4 b% c% D
} " v4 ?- N% i" z) _ H9 { removed = parent; " T I; Q: K* w5 r parent = removed.parent; Q! Q; o, @0 P/ |6 K' ` } else if (uncle != null && uncle.color == COLOR.RED) {" Z5 e$ \5 I) ?7 _- o- [8 r8 p: c
// 3.兄弟为红色 8 C( ^6 z( q% j* K) t rotateLeft(parent); / s* N/ t0 K+ C4 t7 Z$ m6 x% p, V* X COLOR color1 = parent.color; , b6 A' ]7 M8 d" G) P parent.color = uncle.color;4 n& L& a& R8 H; _# d& w
uncle.color = color1;) x, c! Z. `" {" ]
// 变成第一种情况" ?3 G- `4 H0 h
} else if (uncle != null && uncle.color == COLOR.BLACK && far != null && far.color == COLOR.RED) { $ M7 A: J; e/ I4 c% e( o' X* ]' E // 4.兄弟为黑色,远侄子为红色/ d/ j" L! ], F6 M
rotateLeft(parent); ) L% X$ w" m5 A* h7 I3 x/ W7 K COLOR color1 = parent.color; 8 L' T! u) a5 H% O2 B2 R parent.color = uncle.color;2 C. A2 Y4 I& {5 ]
uncle.color = color1;! C1 p& q0 w8 b, K9 E
far.color = COLOR.BLACK;& Q5 M; L1 L* T+ N) s, O5 C
break;6 I% S5 x) q5 ]# k
} else if (uncle != null && uncle.color == COLOR.BLACK 4 c2 Q1 J% g) G! d && near != null && near.color == COLOR.RED& M% h+ L- ?4 h/ e1 [$ ?% t
&& (far == null || far.color == COLOR.BLACK)) {) W) T0 a. s% ?
// 5.兄弟为黑色,近侄子为红色,远侄子为黑色( q7 C6 I5 i# \3 p7 q
rotateRight(uncle);: j( G( E$ N* i! S! j
uncle.color = COLOR.RED; 8 {# c6 O5 F0 t! S near.color = COLOR.BLACK; - O* l( Q" s# c8 I8 `& j; x rotateLeft(parent);% l: T$ J) B% [5 V
COLOR color1 = parent.color;8 y+ v. ~6 S# ?# R; \; O/ w L: y
parent.color = uncle.color;+ Q" w* D- x7 q! ?# e+ ^, p" }2 N+ [
uncle.color = color1;7 c0 f" R1 y( W5 h+ F
near.color = COLOR.BLACK;. p0 A% Y2 w/ F/ F4 k
break; ( l# w& f3 z' A) ^ } # d5 a: c. x$ J) y6 j/ r, M' y. i7 | } 9 G' y% S1 y( S ( U+ z p$ D: a1 G# h% L+ } }else{- r) w2 n$ H" ^+ t
if(color == COLOR.BLACK){ + k5 Y9 U0 j8 f6 A+ h; m( I while(parent != null) {4 [, W8 M& E- I6 n1 L0 F
uncle = parent.left; ( R, F) j9 |* H2 H RBTreeNode near = null; % M+ a* ?% j5 d RBTreeNode far = null; 6 Z/ O6 f' e8 z5 y if(uncle != null){% B$ M. t9 J; X& L5 m
near = uncle.right;8 p/ x/ \6 k# V- B1 |8 _0 J
far = uncle.left; - J* y- E5 o7 d- @# q4 g }/ E4 v- o3 z# g5 G7 [$ _- h
if (parent.color == COLOR.RED && (first(uncle)) && first(near) && first(far)) { ' W) [; \- N# w1 }' z // 1.父亲为红,兄弟和侄子为黑0 Q2 u- b4 v8 k/ G
if(uncle != null) {" `# f5 E/ e9 z) w
uncle.color = COLOR.RED;5 D U, ]3 }" c
} ! f _' J! D9 G' _- S9 |& N parent.color = COLOR.BLACK;- V% u" x! u. t
break; 2 c/ g2 U3 t, ?0 X0 s P" X* G1 l" A! S# c. }2 e: p
} else if (first(parent) && first(uncle) && first(near) && first(far)) {* {0 J5 U* e5 s* {8 n! o1 B
// 2.父亲,兄弟和侄子都为黑色 ! f, e/ Y7 Q& s* u0 A. N if(uncle != null){ & u, t1 P! [2 ^( n$ I! r# Q% G5 h uncle.color = COLOR.RED; 8 U" k i' A) z G } ( v# p% i/ u0 R' J! r removed = parent;- B1 y/ g! x# D! j" f6 Y( x+ C
parent = removed.parent; ) j' O* C7 O5 {8 g8 K/ ? } else if (uncle != null && uncle.color == COLOR.RED) { . `) V4 k; k: }. H- p. g( a% B // 3.兄弟为红色 # o$ W# \" N% r: K; ?! [: V rotateRight(parent);9 A& w/ e+ X3 T9 B1 {6 |
COLOR color1 = parent.color;' _$ |) h1 P% p- E q7 A3 \1 P4 U, c
parent.color = uncle.color;% U* @( V$ O* E7 U
uncle.color = color1;* Y- ?& e0 d' w! m6 K: ]
// 变成第一种情况9 y) j& s8 S1 H% n0 K% t
} else if (uncle != null && uncle.color == COLOR.BLACK && far != null && far.color == COLOR.RED) {5 {# U$ ?0 i2 q& `
// 4.兄弟为黑色,远侄子为红色, A ^- T) j! D& A
rotateRight(parent); : q" T( B8 ]$ a' C COLOR color1 = parent.color;8 H' \* U6 E' Z& Q; P9 G
parent.color = uncle.color;5 P% ]; h' [' U# E9 R" ^
uncle.color = color1;" x$ F* m( X! h. G/ U
far.color = COLOR.BLACK; 7 Y9 z1 @) G0 U3 m+ _ break;- E4 m: |/ `$ K2 N; b0 x* Y
} else if (uncle != null && uncle.color == COLOR.BLACK 1 I( z% p+ u) x$ T" s! ? && near != null && near.color == COLOR.RED ( K i% m2 R0 ?) E && (far == null || far.color == COLOR.BLACK)) {+ e9 V9 w0 D: I0 G Y( v) r5 A
// 5.兄弟为黑色,近侄子为红色,远侄子为黑色! z/ u5 [9 x1 [
rotateLeft(uncle);! I9 O+ m& \( Y; V
rotateRight(parent); 7 h/ M" K9 a( K COLOR color1 = parent.color;. P. v$ x0 E, n" N8 ^* v
parent.color = uncle.color;- b* t: G4 E8 } l- X) _0 ~/ {
uncle.color = color1; : ^: b* Y) _: D- Q. W5 H* D o2 y near.color = COLOR.BLACK; ' h6 F4 W6 {( {. x4 {! B5 z break; * o9 w! U r/ C& t4 o) ~; j! C. P }& U/ F% ]1 W& n: i! v! d: c. S5 i6 S
}: Y: _7 k# ^; ]4 v! L/ v' _
# [* s: T' I' z5 B, B. b) V1 d4 ]
} 7 x$ o. v" O6 w$ R5 U0 o- J } : _& s( x; @' W3 S: [1 I! s9 r }while(parent != null);' N7 L/ L; M4 b/ D
' D% Y* C, J: D& Z2 {" c W } / Z5 \) N2 l8 }* s [ private boolean first(RBTreeNode node){ " @% y" r4 K9 C return node == null || node.color == COLOR.BLACK;. [0 y/ ]3 M- c: s+ M/ v
}* L$ l' T2 a% k5 P6 v
private RBTreeNode getNode(int val){ % I% @; L: Q$ K1 s$ m, A- B& O if(root == null){ 7 R7 X& S, q2 l N5 k return null;; `6 T& z7 G' [3 D: Q* p K
}; a9 L+ C! r6 T4 x) R3 z# F0 ?1 n8 R
RBTreeNode cur = root;. Z2 ]3 W1 i+ E2 _& ^4 ^ _
while(cur.val != val){ 0 l0 b/ ~- f0 l, W1 I if(cur.val < val){ 1 j, y0 V) k2 u" }# v0 |) q- ]% ?- F2 N cur = cur.right; 0 f" P- w* L i1 k }else if(cur.val > val){& j3 p$ Y2 H" ?# N& H/ i
cur = cur.left; " }; t2 C8 L0 I; [7 p2 K+ \ }$ s, D3 u* z) q8 y" y) t% y
}! {2 F0 Q: l) Y9 X; i
return cur; ) `6 h& x8 R/ n$ ?9 ^: Q } 3 S" H* [* ]; R( \+ H' S private RBTreeNode getNextNode(RBTreeNode node){ 2 ?% K& V, m) e& m if(node == null || root == null){" }+ y# K. w$ O7 r) {5 E
return null; 2 u. S$ m4 V; o; w: B }8 ^* K" y- X. s3 Z$ C$ ]% p
RBTreeNode cur = node; 8 ^( ]: |* X5 c# T8 ^( q V, E if(node.right != null){ g/ d$ V9 ]# y node = node.right;/ L! k7 F3 B; k5 I* ^2 h# w$ c
while(node.left != null){. y; }; A% U4 L6 o( |. S
node = node.left;+ V4 m4 }2 {/ Q/ k+ t' N1 y, L
}' F: q- s1 J) B, u2 t) J
return node; 4 S: |% z1 u' S }else{ " C4 ~- k+ G% l; {2 Y RBTreeNode parent = cur.parent; J2 z/ s6 X+ M while(parent != null && parent.right == cur){, \/ H% d) N% F+ A1 f$ w
cur = parent;- o$ B$ a1 f7 o# ~9 B- K
parent = cur.parent;) h" L1 w8 d* N# g5 X
}- u7 E# ?8 p" L, P1 Q$ L5 w
return parent; \' b3 Y0 A2 g$ g# C
} , `4 U% d) r* q/ w% | } * l6 B' t4 T3 C* m9 v ^ 3 m3 ?8 h$ Y* g+ L% u7 h! j: j————————————————; W0 K5 k- o/ m0 v& y' p
版权声明:本文为CSDN博主「囚蕤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。1 o) i+ Q8 K. Q" X/ {/ O
原文链接:https://blog.csdn.net/weixin_52477733/article/details/126787471' q k3 U& s& L7 Y4 @5 K6 |
f" g$ ]5 l. M( a