#!/usr/bin/env python . [: _: V( C% X" L# -*- coding : utf-8 -*-$ B8 u" N @3 a' E# V) b
/ v; s4 {- o8 _( |import os 4 `" ?7 @2 S" @4 ^+ M, Rimport random % `7 w' ]$ G/ ?7 N S& H 4 Z, C0 I2 c4 CRED = 0: ] F! B0 v2 x1 h! c, A9 u6 R
BLACK = 1' w: R6 s: ^! _. j$ p
# s g5 Z& S' _class Vector(object):! [8 a! L+ ?4 S4 U, E
def __init__(self,x=None,y=None):' `, c2 _6 e' B( w
self.x=x) r" \& k; o8 y: K; l* p+ w8 T
self.y=y$ ?! X1 A7 t+ e+ x
) U2 r$ T) \3 i! k
class Node(object): $ e0 H9 d! \# Y4 K& { P """docstring for Node"""$ S9 b' N! b: D: {$ Q
def __init__(self,data=None,color=RED,left=None,right=None,parent=None):2 r4 o6 q1 _1 ^8 f, X( y) U8 K
self.data = data . @; I% @- I' Y( r2 u# h' O5 M1 A self.color = color7 N0 l) z& N, i* r
self.left = left, c! p! u1 n0 _, b
self.right = right, z: Y6 i0 J2 e# e/ u
self.parent = parent9 P# a: v* S+ q0 V) t Y
8 g1 t& t- B8 q. L
class RBtree(object):3 J w$ y; x- X! L: X1 u" o* Z
def __init__(self): 2 ^( h( F: |0 X* y' n8 a( @ self.root=None ( N5 K( |: Z/ Y$ M2 G; }) r self.size=0 6 l; i( _ x/ c) F u: C, x: d8 u B+ d9 w9 o; f
def rb_rotate_left(self,node): 1 L- k# t9 @3 F: }! [ right=node.right 7 K; d2 n4 L! e% h: {' `1 T- B; ]) ~( w' ~2 H0 B( V% K
node.right=right.left f" @+ c! k2 {9 V: K
if node.right is not None:8 R9 }* P8 g! O- y# j, L
right.left.parent=node % m* G8 z' |* O+ T6 y& q 8 Y0 N& e; P; h3 F right.left=node & j5 ~( M0 I9 L7 x4 Z right.parent=node.parent% r- Q7 [' d) a4 b6 r6 t; K
. ~0 ~. L. t% J/ Q5 V0 ] if right.parent is None:( N7 T8 J4 I' [3 \3 I6 Z6 W( |0 ~
+ l% Z/ P9 {2 d7 P0 Z% g
self.root=right5 x. q8 l7 y9 `8 ]
else: ! B8 ]9 u' [3 F, ` if node==node.parent.right: 2 Z, T# ?" T: h A node.parent.right=right - ^3 a" z3 r# g else:. }! Z6 Z k/ a( _
node.parent.left=right5 L- j v; ]! A% H) Y' A6 S$ U
node.parent =right 9 C5 v' O G# x1 |+ v 6 i. y0 ~/ y3 d8 j7 a3 p+ D , n* h2 t0 N% f$ C2 G3 L: z def rb_rotate_right(self,node): - C! I) }% }: n; n( z0 z( r- c0 D left=node.left$ W$ u, X) u# E8 A) Q) u% o3 h
node.left=left.right " D, n4 ?5 y# r / Y% s8 O; g j5 \$ i, y if node.left is not None:; {+ Z, \$ i4 ]
left.right.parent=node 2 e0 i1 S9 i7 L; \- F( {" c, ?8 ?0 c+ V3 F9 |
left.right=node 3 b0 e6 \6 A$ C left.parent=node.parent' }) s* V# _+ K5 z: T1 A" G+ a0 [: D
P* R4 `' k3 g( d
if left.parent is None:8 O6 _! ]( l _& D4 \
self.root=left% z; u% z' w |' N) h& V5 r
else:2 [# Y! Q! {9 Q% r4 E( u$ h
if node==node.parent.right: ' B! o* A* i- s p node.parent.right=left% w; P/ K2 S; \
else: , p4 x h7 c. c; H( h node.parent.left=left$ J" |$ ?+ t/ a( h* R
node.parent=left, U/ g7 A) w3 J; N/ L
0 m4 T* d( b! B/ H- l8 o2 @9 u def rb_insert_rebalance(self,node): - `( `0 v: i f parent=node.parent0 K/ m, K, Y$ D. `6 q
while parent and parent.color==RED: ; F8 R7 ^0 T& t' ^ S, P4 s' q gparent = parent.parent + \0 e5 @$ \9 k/ S if parent==gparent.left:8 |; Y5 A9 j; ^2 n
uncle=gparent.right t3 L' s7 G* ^1 G7 `. P
if uncle and uncle.color==RED:* w0 N+ k! \6 @) j# c0 ^6 K3 p2 s
uncle.color=BLACK C( _$ C0 K$ }# B7 M( B parent.color=BLACK3 I( _ H8 A( T+ f/ R& F( I* w
gparent.color=RED 0 f5 T1 ^( I. \1 ] node=gparent " U3 M: f/ ?# \2 o$ m else:3 [$ T+ v0 y/ K) T! T
if parent.right==node: . r) v9 y6 ^0 |4 h self.rb_rotate_left(parent). J. p0 s4 T4 z+ J+ ~# s
tmp=parent 9 v" p) w. a8 } parent=node 8 {) q! w' v9 }# r node=tmp* j6 \" C# w4 o* c) Q" ~. M# X
parent.color=BLACK: p% @% `& V6 {, u, L, V3 s q* C- z
gparent.color=RED - D- ]( x* @! z' ?: t1 M $ Y9 c! X" @; X1 B; U self.rb_rotate_right(gparent) , c; I X+ U0 b , f4 D3 q: U/ @5 E. [ if uncle:& g6 e E* j3 {8 e4 Z3 b+ c' ~
if uncle.right: . e3 e# G& Y5 A# v! B. g; b- y node=uncle.right * h3 ]6 \5 o/ S2 C( w+ e1 a else: # X! O, S1 E: |; T8 o4 z uncle=gparent.left ( ^9 ]/ \: q+ s1 P' } if uncle and uncle.color==RED: 1 c7 J2 t0 n2 u uncle.color=BLACK 3 C$ H$ }2 o/ g: c9 e( D parent.color=BLACK # W. n8 L% u& p gparent.color=RED & V8 ?: {) ]3 }0 l node=gparent ) |+ d+ s$ ]' [6 d else: 5 b! j' ^6 { t. X4 M if parent.left==node: 9 }" g' N1 t3 ]7 R; j self.rb_rotate_right(parent) M# X5 T5 k7 ^8 c- g- C6 { tmp=parent$ E6 I' R7 O/ Z r: _) T8 e
parent=node: z) i' t/ G! l' O* H; c
node=tmp ( V/ L/ e- D+ S' G/ l, A0 @ parent.color=BLACK 7 r7 h R5 F/ ^; F$ W* e& A8 k gparent.color=RED " b( V8 m$ K) |) ~ self.rb_rotate_left(gparent). h8 T( R+ [4 `# Q4 q& d
9 ?0 m: ]2 v r" g- R
if uncle:* ~ X) O" ?' t7 H# k$ J$ _/ m
if uncle.left: : b) ^+ i- U/ o5 w node=uncle.left5 F+ H7 a! |1 @1 _8 d) v
parent=node.parent 4 v. h6 K" }+ Y5 |9 g& u* M1 i1 n, ?" F% N6 Y8 M
0 R0 [$ X* A6 t' c
self.root.color=BLACK & E* n4 V% O& b1 H, F, P * t; J d1 A/ c6 A/ j * z c0 y& [ S. P8 D
def rb_search_auxiliary(self,node):: y/ k( z8 A$ e3 S
tmp=self.root" v- T: w0 i' @* n5 B
parent=None ; t& B! ?4 _$ E" `; L6 n while tmp is not None:6 O$ m3 ]$ _* q( S% n! E
parent=tmp , n8 H: G, h/ I- T1 d. D% \ cmp=self.cmp(node,tmp) . B. `5 }0 G: i' \) l if cmp<0:# u% m$ p- b% u, P
tmp=tmp.left 2 r: _+ H* @8 E6 h- _: ~5 \+ A else:% W: ~2 m/ K5 I. G( Z' P
if cmp>0:. @" S. _7 {/ T1 c! ?
tmp=tmp.right; O+ G' N3 Y# A2 i2 t3 u' b9 ?
else: 1 W1 I3 [' p" S. n' \; l5 h% | return tmp,parent) c' E' D$ _% M+ v0 \' H+ w
4 S0 K% E! ]; f9 p: s ^) q' g return None,parent - H7 a6 _6 l/ S$ I# S8 M$ t. D& q, L7 \
def rb_insert(self,data):7 w2 a7 p! V( w. H' m' s
tmp=None; {) m3 W1 ]: e! J
node=Node(data) , u* O8 y2 r2 F0 L; [" w$ } tmp,parent=self.rb_search_auxiliary(node) 5 z+ j2 z8 ?6 w$ W; a2 b' { 5 x% z3 n: c4 V0 W- M: N8 C: Q if tmp is not None: " G& d8 Z: n, s2 ]8 P5 w* O0 Q return $ M+ `0 K9 d- ?$ o' C
% X' S/ I. e% T& q
node.parent =parent % o6 N; M+ w9 I& I9 K node.left=node.right=None & v* J8 X6 \' C4 L1 f9 B2 C node.color=RED . d3 x; f% r# C. Y* e- D" S1 s" S : M) o1 Z6 }$ s: l2 W5 t4 b if parent is not None: 2 V# F5 w; A: W2 e% B" p" F) y" ~* ~0 |2 [
if self.cmp(parent,node)>0:& w7 q; D7 |- C2 Y" l* \7 o
parent.left=node % ^2 w7 L* x( [, c. g# C/ q- U; w9 S( s else:3 n5 \4 L9 u/ i/ j
parent.right=node; L- M9 T+ d5 L6 Y, r3 ?+ n
else: * |: g: }( X+ W2 i* v: u self.root=node ( ^) }) }- T: C. t9 c0 D) ? return self.rb_insert_rebalance(node)# z& n8 x0 m& ?5 b; X- J
( `* e; A+ p7 j. b def rb_erase_rebalance(self,node,parent): . \# |0 k& J6 u" r while((node is None or node.color==BLACK)and node !=self.root): # `: P+ |" ^1 F1 Q, n$ M$ z if parent.left==node:0 Z, k! S* @" G1 g- `* Y; z4 [
other=parent.right ! D; @2 |/ [- ^/ Z if other.color==RED: , b* T. M; z& ? other.color=BALCK* [. p5 {3 x3 Y3 d; t h% |1 Y
parent.color=RED ( x- Q0 x( V( Q. K8 ^" q* A& _ self.rb_rotate_left(parent) & ^3 K* k- {6 Y other=parent.right, ^2 N: u0 v& A* r$ |. S% X
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color ==BLACK): $ k7 C' C6 x. ? other.color=RED: S; |9 D) Y/ B) h
node=parent 4 n. `9 h( F2 d: C4 z, @ parent=node.parent * V, ?. K" x6 U+ Q1 o+ Z else: _$ H8 o* F/ q; c9 h% Y$ K if other.right is None or other.right.color==BLACK:3 Q- V1 Y1 `1 h8 i. ~4 O' Z, t
4 u) K( `/ W0 X if other.left is not None:7 n# n R$ V7 z
other.left.color=BLACK" B: m; J! O# r' q# U1 c
other.color=RED 6 T! g- C" g+ `" b O5 j6 T self.rb_rotate_right(other) , U2 q a& S, Q' r+ i other=parent.right( E4 r0 w7 [" U0 C/ U! S
6 _( O$ j8 }, S1 I
other.color=parent.color5 c N$ A8 X! \7 F& e
parent.color=BLACK/ n, o& l, P2 i3 D6 u
if other.right is not None: % v' Z+ O% F9 k7 r# Q other.right.color=BLACK4 R* A: \* N* T) t
self.rb_rotate_left(parent)0 t7 a7 h7 J! A9 A) x
node=self.root 3 x- ^- _# {/ l5 i, ]: C% d0 S break( ?' S* j& c' z7 u/ \: H( c# W# q- w
else: , H5 \8 B/ K4 k; V5 [/ ~1 G: b other=parent.left @% b" y2 P8 W$ m6 l9 S6 o
if other.color==RED:% ~$ _9 R) S4 D: v) d. }. B
other.color=BLACK ! z- D& D) L1 f2 E8 `6 t) o parent.color=RED# R# D$ q6 X0 B8 s, m) U
self.rb_rotate_right(parent)) l+ W" H8 v# M4 M; n
other=parent.left * \! g4 P' k+ P6 {" F- ^+ G1 @ if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color==BLACK): % G( C5 j! |6 [" B other.color=RED, j; c3 d, o/ a; i' ]
node=parent 9 R/ x9 ^2 Q7 E0 M# y parent=node.parent % u+ h5 z# K+ k* v$ o; T else: - l* w2 H$ g5 a/ a6 w if other.left is None or other.left.color==BLACK: 6 G# g" X* x R' @ if other.right is not None: 1 i! O7 _. `, H9 u( G( r4 p$ W0 b3 _ other.right.color=BLACK+ G+ b$ j9 G0 i/ z
' _; `) F% D$ u6 ]% W other.color=RED 9 h4 f r3 {& G7 z( ^9 m: I* a self.rb_rotate_left(other) + B' E& I$ P: J# V. q; C- B9 k other=parent.left! F+ z |# j# V9 @. s
" {0 a7 s0 \# Z$ K! |/ G+ i/ s
other.color=parent.color 1 g# a, `0 g8 q" F* w parent.color=BLACK + t. ^2 X* |+ d( t% ~* M* @/ r% F7 @% J6 l( ~. t7 C( z- O
if other.left is not None: 7 @; H& I; j4 e2 ]* y' o$ B other.left.color=BLACK 2 {" C6 q/ H- ~- E6 K7 E+ P6 O5 I/ s) z
self.rb_rotate_right(parent) 8 y- ^5 O) b- z9 K node=self.root5 }# M* L+ i! g8 o
break 6 G! e8 u: k) n0 C! l& G ) }% X8 f: \) p0 r) Q6 R' k/ A2 o5 G # m. G& V- r' n4 @" ?. @+ t8 N; l) O. f# }" j, x2 g
if node is not None: ' Z$ G1 x% A8 o( H& H0 O node.color=BLACK $ H, O# `* O* ?9 B* i# _" F: W6 x m5 K
def rb_erase(self,data): / p7 E1 I& f0 a8 B0 A% T tmp_node=Node(data) : R- ?7 \% H" K6 K node,parent = self.rb_search_auxiliary(tmp_node) 9 b# f/ @3 Y" g [( r! e8 e5 T if node is None:& J* }9 \2 B& b: c
print "data is not exist." X/ M. j$ \+ ~( C" G/ w7 j& O
return 0 Z+ Z1 ?, O# e 2 R$ X9 u3 F! `, l7 d6 W old =node* D9 _9 Z [, s
if node.left and node.right: . y- s& K) z. ]- h node=node.right ! C' f. L' S+ t" d) f + `; K8 D! [9 F8 D3 Z0 f left=node.left m' t( z/ K2 @ while left is not None: 3 I1 f6 F1 a h6 g" i1 d node =left / e- ]" e5 e9 L2 D7 L left=node.left - T6 [( X, V" @0 Q" s" U3 B6 s- P 2 L R, O6 A* p* ]$ f child=node.right# r- @0 ^- {! B. G8 G; K& I# {
parent=node.parent+ S. B) [( o% L9 x
color=node.color & d0 X2 p3 l0 q, E+ K1 M # {% r# x# ?/ }, l- r2 U if child:/ E8 M, P: j0 i. j. ]9 B/ r
child.parent=parent " z2 h' b9 g6 p- b/ P3 K if parent: ( f" n: m1 d; X' W if parent.left==node:+ H/ b$ @, N" [: r! A u4 z( J
parent.left=child; @" ?) n. {' [% g5 c* L
else: / Z7 a8 t4 P+ S5 c parent.right=child; G6 T5 n3 A- G) a& q4 e6 C
2 ^8 A( I, d- [$ Y+ c) R+ k2 X if node.parent==old: 9 E9 }! ?' R3 ?' [: | parent=node % ?7 D1 D: B1 P6 s- {& @! c* \ node.parent=old.parent ; j& u/ x2 ], Y node.color=old.color1 l0 C5 n: E3 j( t: g; z/ w+ A
node.right=old.right. _; _$ j7 a; y5 d; G0 f
node.left=old.left4 d7 |3 U: Y$ h/ Z3 p8 ]
( `1 B% g$ D! ^; N8 X2 ^3 k
if old.parent: + i% w2 k5 Z; G( }$ z3 i if old.parent.left==old: ! \+ e, q D- r5 H old.parent.left=node& V8 m4 f. `7 W
else: * n4 {4 ?: C' Y$ ?# S$ o" h old.parent.right=node & }- a4 v) X1 q4 }2 D% f' @ else:" W" r% @# c `
self.root=node % h* p+ y1 P6 R" H/ d; w- i3 Q 7 t+ }8 v: b+ E6 [" O0 Z; R5 u& F old.left.parent=node* R, e5 c$ [" e4 B! [5 _
if old.right: ( g1 T. x' N6 K6 u; _$ ?) X5 h old.right.parent=node , L8 p) t) m7 Q) B5 b6 i+ V( C' f. q* ?
else: z( v" X) Y, X" P if node.left is None: % i: ~: I+ \3 [ child =node.right0 O# j' S9 j, ?+ J8 d' R
else:/ v% _9 Q, z3 P: u
if node.left is not None: 3 f' m: A% Z% }# p+ p2 } child=node.left " V1 E4 M4 F, n- ?3 p1 E3 P else:) j9 Y& h, c4 T) `
child=None 6 G( N: Z2 Q7 a- i, W8 P parent=node.parent5 ]; B; k2 K# l% N9 _2 W6 R/ Y
color=node.color & C+ z6 u7 [ {1 S( Z. b. w+ } if child: 5 r. ~" @9 k5 L% D6 ^ child.parent=parent2 }( l1 f6 Q( M: K* I
if parent:2 h4 Y0 P+ V( I$ j/ j
if parent.left==node: & I) t, N$ C% y1 [, P parent.left=child# _6 x/ A- d4 Q4 r- R% h
else: ; @6 [1 X( R; P# C9 q7 K, v parent.right=child , o4 w0 `9 ~# M( \8 q else:8 E( V; n/ g2 _0 R, V9 a7 o: C
self.root=child" j o0 J, U& H$ G Y" Q+ k3 |
& F, S0 }+ w0 t# r" _8 I if color==BLACK:: A" `# G' f! c9 y8 I
; j8 m5 m3 o# O3 L- j* V
self.rb_erase_rebalance(child,parent)0 P) ?/ `4 H* \/ c) n9 J+ P
' v- H i- V: J; z; Q9 X+ y . `2 o4 a5 d% a' Y* t def rb_travelse(self,node):8 P6 `3 m7 }( g
if node is not None: % u$ ]* E9 n) p W print str(node.data)+'\t'+str(node.color) + m, Z3 j6 A+ Z! @' P" T [ self.rb_travelse(node.left) # f/ {; e) z' n6 P% l2 c if node.parent:5 Y, `: h7 }7 y6 X$ a
if node.parent.color==0 and node.color==0:) Y; o, e. Z! k5 t, W9 d" ]4 G u
print "error" ' J% P8 \, ?# V* R return& |) B5 j2 \( W* }- \
self.rb_travelse(node.right) ' h" a( I. b/ a if node.parent: , B. X# Q, x3 I if node.parent.color==0 and node.color==0:" Q/ K( B& V4 a/ y
print "error" 9 v2 z6 H! y6 S; I return/ B6 j: {! [/ |3 g) U% V) z
. b+ H9 d! A/ u5 f return% T( ^+ C1 b `3 S1 t' f
+ Z1 V; h4 c7 n! u% j$ D9 R + _ T( ~. S, s, h- o+ d" b. R def cmp(self,node1,node2): 6 {. F( H- g/ k+ e, g' D if node1.data>node2.data : 1 L* X* O6 Z: S5 P; M1 m8 X k return 13 Q6 Z4 D0 N D" o) z, S' e
if node1.data==node2.data : ! a2 ]0 o, c$ l' `5 H9 P! g return 0) F; Z. c3 o' O8 X$ G
if node1.data<node2.data:3 m* e5 Z4 Q/ a/ A+ o$ M- Z
return -1& w) M7 [* D. A* k( I
M2 L4 C! I$ b+ Gif __name__=="__main__":7 L" i3 ^7 a5 H( u/ w) V
print "main" ! P( i* S6 V9 q# P data=[28,6,39,78,6,43,61,56,71,38] 5 D+ I& W& S* }0 m #for i in range(10): " Z0 P, v& \" r! {2 O7 Y # rand_num = random.randint(0, 100)$ o, m \" ~2 V$ L3 F+ l3 h! [5 Y! ]
# data.append(rand_num) # Z4 }+ i; S" G9 D+ S #print data l# Q2 b# F" D6 o- R8 h, z) y. t) d t=RBtree() 9 l1 |' U- V% q3 n 2 S( \, j6 [+ n9 R* s- L* F% g$ S1 _8 x
for i in range(10): ; k1 d9 k* J; p# W& I$ G8 M t.rb_insert(data[i])9 o2 X V, g9 D: [
, E) Q6 H5 b5 @( G8 U
; Z( o0 Y, s: z4 P q3 o
t.rb_travelse(t.root)& o O1 d/ f2 l4 _
8 Y0 U+ z* R8 u/ R$ G, i& y: d; G print "---------------------------------" 6 t$ v3 r3 [' l t.rb_erase(data[7])4 [& r$ K5 O: x- b0 w