2 }" T3 W; k4 i5 D8 \5 g" v0 wclass Node(object): 2 C I$ ?" Z5 W3 z """docstring for Node""") F3 y9 S* z. g: o$ i
def __init__(self,data=None,color=RED,left=None,right=None,parent=None):2 u( Y% G$ W2 W& j- x
self.data = data1 O6 k! f# v9 t' G' a
self.color = color) i$ {% W7 ]4 W& H8 S# T
self.left = left# @5 v4 ?0 y( O7 [
self.right = right 0 y7 N- g6 ~8 z# ?) |2 B self.parent = parent) F6 }" ?7 z; ]* @- q
, j5 @2 W$ H% J0 K
class RBtree(object):0 ^! @0 N ~9 ]! y K1 _
def __init__(self): * ?2 ]4 s( V+ a2 H2 I. D7 O4 p: Y self.root=None0 A6 h, p% x9 y# l; A5 F
self.size=0 ! f4 O0 H. \4 ]4 J9 R; J + t9 x3 Y5 i) L8 {) x$ e8 q# ]# H def rb_rotate_left(self,node): % f7 s* z/ W9 @: }2 h( x right=node.right" ~- j" E! U- G9 I1 c! ^
% o0 K" D4 h* ~9 n7 I1 V
node.right=right.left ! J+ ~% Q2 w3 X0 F1 c6 l2 P if node.right is not None:/ G. V* F6 W9 L6 m* [+ v$ k
right.left.parent=node# R; ~* T+ W$ h- G
. x' A. i6 z* _" g4 @8 [ n+ P3 p right.left=node $ L% p* I' \+ U0 s: `' o S7 X right.parent=node.parent2 g9 C" S+ d0 b* I2 k* S2 D1 K; P
l5 G: z2 D9 B% K/ g- o. R6 x* M9 E- U
if right.parent is None: . B$ l v/ K/ `8 c + N; a" V: W" [5 t4 ~# L self.root=right6 X' U, X$ {' [8 ~/ A; O6 b
else: # M8 }% ^; g( z9 n- d if node==node.parent.right: 8 d R, H1 q, I1 Q) d node.parent.right=right) x5 O1 |5 Z" V0 I e+ Z
else: * j: o& a1 k- J& `4 X- E node.parent.left=right 9 p" r4 {% ?$ i: ]' @9 b node.parent =right( k2 U, l0 `5 n0 P. X
/ g, L; R+ `8 g' Z+ j: U
. Z( K6 r% ]- f* j( [) U3 n) S
def rb_rotate_right(self,node):; v Q5 j& f) ?
left=node.left0 U4 o. Z- }7 n& O5 g; h
node.left=left.right2 G$ ?; @& G* r; |
7 f2 h4 @4 B6 S- w! O if node.left is not None:, s6 i( d2 {$ E) c2 Q' `
left.right.parent=node$ v; m" x/ F- d0 R2 V9 h% D5 }, u
! {! W; U! H7 \9 Z, f left.right=node& V# y, B# E4 P' |3 U
left.parent=node.parent, @/ c: ~* ], m& o
8 |3 w$ Z) i4 @& P/ e' H7 R Y# E# t
if left.parent is None:; A2 X* ~0 P+ Z9 L' M
self.root=left* l0 u) D6 x8 K
else: 9 [2 K; {, Y" k7 T" ` if node==node.parent.right: 0 }; j4 G; \* c9 U) [5 s+ o. b node.parent.right=left5 O$ q# [7 f- `/ t
else: W/ B4 u& F) Z* a node.parent.left=left* C0 C5 a7 D* @* V( C
node.parent=left 1 z. T1 \( ?! Z5 s: a, s2 t& B' u6 P' I
def rb_insert_rebalance(self,node):2 O, G; X v* t6 o
parent=node.parent / c7 Q* J" c2 U1 q' q3 Q; | while parent and parent.color==RED:+ l4 ~" G5 H+ U( |' h$ e. m7 u
gparent = parent.parent7 }8 G" g. o& r; }0 p& [& |& m! i
if parent==gparent.left: . ^9 c' L' s5 S uncle=gparent.right - v& @+ d9 h" |/ d# c( V0 v" [ if uncle and uncle.color==RED:' j _( V: Z" c* ^
uncle.color=BLACK % J' `/ B1 v! K/ A parent.color=BLACK" i' T$ L# f1 H n
gparent.color=RED. w6 f f8 A) r) E
node=gparent : X8 y% M9 |: s( h else:) M% F' t5 S# ^: [
if parent.right==node:1 u8 \( {% O. K4 w3 l+ b
self.rb_rotate_left(parent) ' g% ]9 t8 Q+ q tmp=parent + i4 l7 Z' W+ G/ X+ f7 U% C4 g' M parent=node 7 k$ l8 M! {- U9 H9 A: X$ B& r+ I node=tmp2 ^& d6 R, U! O# o1 E3 u0 z$ W- [: y
parent.color=BLACK 6 |) W1 E* B2 ]' f$ g5 s gparent.color=RED( W2 t6 @. a# }: C
# _; C6 b$ I, b3 C% ?
self.rb_rotate_right(gparent)+ p, _5 s5 m& y Q3 z8 _
9 u" l4 w2 D3 H
if uncle:5 c, G7 a" x9 D+ R. l; W" ]3 c
if uncle.right: " V1 [# T- a" X node=uncle.right . s: g5 [% B# l" x2 [! w# P+ M1 J else:% k. z9 m B- U3 c
uncle=gparent.left8 d1 B$ i. E, G6 I
if uncle and uncle.color==RED:7 V+ Z" C9 q4 ^- B. h% \2 h" g0 F
uncle.color=BLACK 5 \% ]9 Y, j; x. E3 O% r U1 L- ]3 H8 ` parent.color=BLACK( u4 e/ o$ E2 [! L' s; F0 b
gparent.color=RED8 ~& n6 h+ \# C. l8 f# J3 u
node=gparent * d, i s$ e, h5 w; \ else:; M' Y6 P6 \% Y' h; c0 o* Y. U+ @
if parent.left==node: 2 M" D4 C( h/ [ self.rb_rotate_right(parent) & A( F6 K8 ^" X9 e tmp=parent 4 h1 s" L7 c; h" R7 | parent=node; t: I0 a+ t) R* i
node=tmp0 R2 S2 d) A: ]3 ^$ ?
parent.color=BLACK ; Z" Y3 D6 E" t gparent.color=RED 5 m3 D4 p& a: f: u self.rb_rotate_left(gparent)9 B2 P4 U( j* D y" a( ^
: o' f# U% M! H if uncle:# y9 W- m+ j% P+ ^
if uncle.left: / ]" {, l0 w' B; t. n, s2 f& c9 m node=uncle.left 9 J9 e* g% \/ N: |! h% C y5 t parent=node.parent 2 C4 b; C/ C9 H' `* i0 {* h1 g # v/ B3 E# H4 ~* T. ]) p , B( \; D, D, m q( {9 u, B6 z3 y self.root.color=BLACK % ?! @" }9 L0 _3 r. p! \ % w0 Z6 h2 F, A2 ~' l+ B1 N ; S5 O1 v8 A3 h% e. M P) e
def rb_search_auxiliary(self,node):! L' I/ i8 |# h6 ^& t4 ^) w
tmp=self.root. r1 h% [8 Y$ w. _" Q
parent=None ) F4 m: a x9 T, \/ ^" s while tmp is not None: 6 q1 H( L$ [4 a/ n4 e8 Q- d' R parent=tmp ) z( X8 Y# a/ E2 }" x0 |% }) o& l5 K# A cmp=self.cmp(node,tmp) ! W6 |7 m1 K& R if cmp<0:! s0 F% v" k( Z6 \
tmp=tmp.left1 c; J/ |7 `, j8 [$ @4 i7 k
else: 7 K& F" R R/ H- K$ b if cmp>0: t+ p, P+ @& C- b) k
tmp=tmp.right) t7 }0 H. P8 p+ o+ R0 _4 k
else:; [5 f( K) ?* z6 L) a
return tmp,parent& N3 S" ~" u5 l$ R
& \3 D: \+ f1 h }( `2 P
return None,parent ( q, g8 C( Y; R% y9 D8 P, F0 t- C 4 o* B% H( W! ~' ] def rb_insert(self,data): , B3 G& Z! ^; V, {8 R, |2 h$ a tmp=None3 O8 g7 E/ J1 h% ^" |
node=Node(data) r5 W* {' k- L( C% v1 y- a tmp,parent=self.rb_search_auxiliary(node)! r3 z8 k3 t3 c; }" o
$ Q' i$ S3 I I8 ]9 I5 e if tmp is not None:% B' n! W% N1 ^! v
return ' w# Q+ l, ^! I3 |& ~8 _) ]- o J6 ]3 [) @, b ^6 s! h8 a& `
node.parent =parent 9 o3 K6 j7 C2 V2 R; E, k, s3 w node.left=node.right=None ' ~5 O( `& C% z' A node.color=RED 8 Q; D2 l2 ?% w! _7 L6 @5 u4 p ; d( K: b" V+ o# ?+ a if parent is not None: 5 f4 Z' Q N% ~- o 9 \$ p' O! o- y- O if self.cmp(parent,node)>0:7 o P, p2 }$ N; j5 ?0 l* k; m
parent.left=node + A) P0 M$ k7 G% f0 @ else: " r* N$ ?1 |$ P parent.right=node! G8 N; e+ d) W' c
else: ' H5 M9 r1 p+ w9 k self.root=node 6 W- w7 k( m ?" O) M9 S' E2 F return self.rb_insert_rebalance(node); y- L$ z: W8 T j9 z! s% s K
4 r9 M+ [2 d9 ~# [ def rb_erase_rebalance(self,node,parent): ! n5 P6 z& _$ g" ~" L" V/ A while((node is None or node.color==BLACK)and node !=self.root): ( g2 v4 Z6 Y5 i if parent.left==node:" J" z+ v' A$ F, H
other=parent.right - ^& I! G8 |0 l f if other.color==RED: 4 x, U2 W. l3 p8 c other.color=BALCK! D) Q; a1 t" d: C
parent.color=RED% Q9 u4 e3 [ [9 k# T
self.rb_rotate_left(parent)& Q$ z. b$ z4 X+ s- y$ Q
other=parent.right 4 k- O, p0 T3 P9 G' Q$ y if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color ==BLACK): ; ^- [9 X! k( T other.color=RED, @4 d6 P9 p1 k, i& h
node=parent+ k5 y& a. V; l: {
parent=node.parent ( B3 W) d; N8 c& y' M& C else:5 y9 O) s5 h# T4 R
if other.right is None or other.right.color==BLACK: ~; j$ Y4 W$ W: f1 N) \7 D8 e8 G1 T$ x
if other.left is not None: 3 L6 M" ~6 P3 ~$ d: X& `- V other.left.color=BLACK q! r, g2 k: a1 d! y4 q7 U$ x- f% H other.color=RED9 d$ v: q' L; U" |
self.rb_rotate_right(other)0 v4 ~1 \7 N, ?3 O. m2 K3 F" D
other=parent.right9 d8 O7 N- r" d
3 i; w# G$ ]5 L1 @" h other.color=parent.color : o7 O& |0 ^1 x5 F. h; q7 N parent.color=BLACK 3 ]( F6 h+ d5 L% v G5 y* I- W9 } if other.right is not None: . G$ V& R4 t! l% V other.right.color=BLACK 2 r) [! q& }. o5 x4 V x self.rb_rotate_left(parent)! d F( w7 s' U; ?
node=self.root R. A% o5 M0 j4 p( ^0 x
break: j4 i; y8 o/ y: _9 a: C
else:- i, n7 D ~7 A
other=parent.left 5 K- L5 V( |+ U* A% Y if other.color==RED:+ @' O4 z& v. q6 z/ ?- {& V
other.color=BLACK ( T. b3 c! W3 w, k: ` parent.color=RED. `5 D: i6 a# i! F6 X) B6 R7 i
self.rb_rotate_right(parent) N8 _) c: W# F, l# P; H
other=parent.left 6 X- {/ x( @7 t: O6 h+ x8 ^; Y8 ? if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color==BLACK):* k, x+ e: V& r! k% K# e3 e7 Q, U
other.color=RED, K. X6 `. ], o- V& \
node=parent) b F) e$ w& ~" S7 F
parent=node.parent ! g" x' M* ?2 _" q- m) b F# i0 C else:* Z- R: ]3 v' }( b* Z+ r
if other.left is None or other.left.color==BLACK: 2 \5 a* P+ v# i9 f6 M if other.right is not None:2 B* B* ?7 L8 P, e$ s
other.right.color=BLACK$ Z# d+ g# s8 ?8 @/ k
. p. l B, b7 v% }6 g, H- P
other.color=RED/ F! ~8 @5 |4 }4 Z0 W+ b% V
self.rb_rotate_left(other): K x2 @% W6 \# U* j2 X1 {
other=parent.left; E3 S% O; K0 a; T( m8 b# C! r8 |
7 k5 e d6 r( u5 p. W% ^
other.color=parent.color) T2 l! N' V3 Z
parent.color=BLACK ) |; n& j- X& A7 b% c& A - n0 V' i; b4 ^ if other.left is not None:3 R6 D' N7 F3 T$ D% Y
other.left.color=BLACK " E% s x8 ?% v7 V8 B& k6 q- N& T. F; R, Y' V. A7 m' Z
self.rb_rotate_right(parent) / v2 w8 Z; X" f8 X$ g node=self.root 6 x5 N. z" }$ x4 W break ! s+ x% y8 \3 p9 o; u, h6 B; V T. m" S( W
; ?) b) D- g: x& `7 B6 I4 ]% ~6 Z9 @0 T8 l2 m6 {
if node is not None: ' q3 c0 B- J. ~( t& t node.color=BLACK 4 U" K& p2 C+ X1 ]
* u+ C# u! ?7 K) L6 L4 ~ def rb_erase(self,data):2 j- E+ q( T, }1 y; x4 Z$ d
tmp_node=Node(data) % ]5 H. S% y: G- Z7 O' }1 Y6 n, k9 S8 B node,parent = self.rb_search_auxiliary(tmp_node) $ S9 e" h I% S% u if node is None:1 ]5 s4 Z$ y7 k# z& j7 \$ [3 I: B. X
print "data is not exist."0 Y# X) Y, F7 D; j$ i0 P
return & u$ c) v0 o, j& e % w) v# g6 }# D% E' u& k
old =node6 r) M* N. U, v: h7 @& g0 q
if node.left and node.right: 0 y) K" q4 n. X' W+ _ x% J. C node=node.right " A# j0 h# }+ v: ^& N" o. ]3 J$ k& K; T, y$ n+ x
left=node.left & x9 Y @ V7 Y0 u while left is not None: $ z- h. N( U( O node =left % F3 ]) {1 m4 M6 b# U' J left=node.left . e4 c- h1 a* D * Y I$ e7 Q2 d( Q9 `: C0 }8 A$ q% h child=node.right& S( Z3 C; V i& @5 V+ B4 f( o/ g
parent=node.parent 0 L) R* w1 L$ @* k8 ? color=node.color& P- s# l4 a& b, a8 M& r
# M: w7 @! [* G; Z6 X: g% M if child:& C: d* c+ y3 d- I, T6 T. t( ]
child.parent=parent$ ]3 y2 m w! t0 e3 S9 y
if parent:7 r+ _, i( h& ~9 b; K% g
if parent.left==node: 3 d J: }! Y2 T5 p6 J& r parent.left=child; b: E" A1 Q! @& o+ G1 G5 L
else: K; L1 U1 F" a5 B1 S. ]* b
parent.right=child3 V, V, F6 t# i& I1 o
7 p6 M5 J% s# R3 C else: ) _4 S1 u5 _% [2 j9 d, Q# _ self.root=child 6 ^& {4 X: z6 Z' X# Q! a' L4 b- }. w5 _; H. B# u0 X1 A) t
if node.parent==old: , R S; }. [; Z4 c; C parent=node + q) l. b6 a* k4 I/ s N node.parent=old.parent$ ~0 m: C! n8 p( J# `9 g/ N. U
node.color=old.color " i) ~0 c5 n$ p& j! l$ Z node.right=old.right 4 ]! F4 m2 R1 _- |% q node.left=old.left ; K1 I5 k$ g- l, z- R0 M, e5 S3 x8 X; ~0 h& C, i
if old.parent: % ~+ b0 V' P9 ~; N5 o; P if old.parent.left==old:4 r0 a E; o9 L# o9 ?# J
old.parent.left=node k1 ~ z1 A0 D: D
else: " M9 ^4 p9 _6 `7 B, m2 e0 u old.parent.right=node* ?# e9 O% O, S6 i
else:: I l- [% P: q& o; Y" Z
self.root=node* ]4 j5 C: v& B: v; }' @
6 a- e* [/ ^9 p% m, p1 T7 g old.left.parent=node3 t I6 @/ f! D) \9 s1 N
if old.right: $ y/ V! @8 m8 S7 Y6 B# ]; g old.right.parent=node 2 C; ^) W4 F9 J/ ^ * a: ^- z( U. N* t E else: 7 W0 V0 {# p; {" J( Y* Y if node.left is None:' z# ^; @+ p$ U2 N
child =node.right $ T0 R* i ]% ]- z5 K7 u/ N( y else:; j g3 T( A1 E% {- k. v
if node.left is not None:5 B! m) i' c* o% g) T' c3 T
child=node.left $ k8 b2 ^, _" F B3 A else: ( I, m: L, N7 ^( `* F2 v child=None, }, S, s p4 q: X7 O
parent=node.parent! u) u3 _1 M1 I8 u) |, F+ b
color=node.color , d: O1 \. r( R" ]2 i' }" H e- k8 G if child: * n8 S6 I- Y% ]9 l+ f& r child.parent=parent ' u( [3 o; `7 J$ ?% C) c; i if parent:3 [. Z7 W- f( R% C7 K& C
if parent.left==node:) v1 U/ @! l1 l S3 Q: _" W( J
parent.left=child ; W: R; }5 i1 t* e# v else: " I R9 o. ]# z7 \0 o: b parent.right=child 6 l& }/ ]8 w" C* J else:+ Q" p D4 h7 f2 ]0 U, M' J
self.root=child 7 F% @: @. J1 C. p) F9 c& }. N, r7 n. S# W D& Y
if color==BLACK:3 x4 J# ]2 A3 [. w9 C" s m
% V6 i: u1 U; P( h% w+ B2 F
self.rb_erase_rebalance(child,parent) ! H. \! c: F* k, K: [$ R8 A9 ~6 A* ~
3 z* n) Y; T$ K. h) V def rb_travelse(self,node): " c. }9 E2 x' |0 ]; d7 k" H if node is not None:+ ~) e6 W$ f" F3 M+ H6 K/ Z
print str(node.data)+'\t'+str(node.color) : \% P+ \ z0 X% m: i: o8 ~) |) b' v self.rb_travelse(node.left)5 X7 J) k' @/ K# l- T- y
if node.parent:# c# T0 D9 `, h: B" u- ]& c e
if node.parent.color==0 and node.color==0: . k) v) R+ X' J2 u print "error" 3 x3 f% X. G+ O- s* i. X3 f return - x2 p- _0 w/ g& i( o self.rb_travelse(node.right), y# H% b7 T. e/ }+ Z4 P$ g6 P5 _
if node.parent: 9 G% F2 u* Z1 E* J if node.parent.color==0 and node.color==0: ) \/ z3 T' h) _ print "error"3 `3 m: o2 ]- e7 d v
return ; D/ v, x) U# a( R f. E! e 9 h1 g8 h5 }2 m1 ~: ^, t return + H1 C( V( q0 |5 I 2 a& B1 N# |, E0 @1 ^" W! M
% w4 `7 ]% W% \: j) [9 | l( N
def cmp(self,node1,node2): / i9 d: {, m4 T/ }4 A# p8 V if node1.data>node2.data :% G1 w" P2 F/ c* w+ j; I
return 12 p4 p9 P8 }) N; E- _& ?
if node1.data==node2.data :) s9 E" q0 ^1 o: J* A4 A! P) M
return 01 f9 C1 e' K% n1 ]( a* l1 a( q: `, B
if node1.data<node2.data:% r$ S) f" o8 p9 T
return -13 R( e0 N: i* P% W
0 {6 N; `$ Z+ o# ^' W! w; J
if __name__=="__main__": $ H) S5 J6 E( A0 M: m# Q* P1 } print "main"' t% ]% X L3 I4 Y* l* l/ t$ k
data=[28,6,39,78,6,43,61,56,71,38]2 |# } I$ A9 n$ {
#for i in range(10):: ]' a! m' g8 ?2 y( X+ N. P, s; Z
# rand_num = random.randint(0, 100)* @( ]3 Z# _ g/ C o" [/ A
# data.append(rand_num)/ L' A# H6 O. [
#print data - E- G9 _$ f. ]$ `) Z9 ? t=RBtree() : o7 ?. t6 k) K8 N) e0 j6 l$ ?+ q
9 R, T* d" N4 y+ x, N& Q; H1 c for i in range(10):: J; P- P8 r0 x" A$ B
t.rb_insert(data[i]) , \! i" O8 _- A( j m! e2 c) I % S* I7 u/ p9 I% R8 w* m( t3 f8 J " t; y0 L& o! R& G t.rb_travelse(t.root) }7 ]6 F1 X2 g/ h: l
, Y' u0 w& i& e5 l, I$ `
print "---------------------------------" 8 s3 I! Y7 ^( _: O8 g2 r. w5 o! F t.rb_erase(data[7])$ x! H, m; s4 ^! g8 d
' e& S$ f5 q& m6 x! r' s& |2 @
t.rb_travelse(t.root) ( I, x) H( T3 M9 g9 F4 `: \3 s2 J$ r3 ~1 O/ J