#!/usr/bin/env python+ C$ w4 n' ?) w3 L9 v+ m
# -*- coding : utf-8 -*-* p) H! ?% A" ?9 n0 a7 G
4 W$ O8 ]% M6 |/ \2 {
import os1 D, P- b' n- Z0 T% ~
import random 8 k* ]/ i' \7 W+ g. K 2 [2 G" `- c; e$ F8 \9 X5 C4 C1 \RED = 0+ t! s! F4 W& ?: Y' y( e
BLACK = 1 9 C. S" v6 K* `/ t ! d7 y( b6 M N t$ Fclass Vector(object):( j9 d( _% A0 y+ v* a
def __init__(self,x=None,y=None):+ A3 w; ~% S- L2 f4 R! N* k
self.x=x1 S: t( J9 f' i+ b3 s* {+ G: N
self.y=y7 d# E5 k% ?6 @& X! u8 N$ X% n
* s6 f' q- v( U. p4 Y& nclass Node(object): 8 b, M; g% c/ N, b """docstring for Node"""- K8 W# v7 F5 m
def __init__(self,data=None,color=RED,left=None,right=None,parent=None): % q( p. C3 P, [; R self.data = data- { K1 t* p0 X( R
self.color = color " h( i% n8 D0 f3 U7 x+ O0 \$ Y# E3 { self.left = left# W% I, e V8 E1 w. O" ?+ O
self.right = right! I# A c" [; w8 ^/ p: y
self.parent = parent " I0 `9 _( E' I5 ?( c7 v% I. ^% X! r8 I: ? T0 p, Y4 r
class RBtree(object): * J' z: r0 I# U& O6 f4 } def __init__(self): # r0 X/ v( e. }+ x4 [! | self.root=None $ X" @0 v3 ~1 W8 y( w" O self.size=0 ; C( B7 k1 Q( M O9 g % O$ `3 [% W) N# f- R! T# @, o: s def rb_rotate_left(self,node): 5 {" F7 w; C7 j" A right=node.right 4 v' R }7 g+ `8 ~9 o( @. E% _4 i0 _1 b, A2 O3 b
node.right=right.left- _! h1 l8 q- S) G. A8 ~$ I9 W
if node.right is not None:% j9 U% w* i+ `: T) `5 [, H5 Z4 _2 ]8 P
right.left.parent=node ' H" n t1 Z1 g+ G/ k. b2 e6 g& T9 e
right.left=node/ E) V5 }) m) ]: e! l
right.parent=node.parent6 y/ u! g9 w7 R
$ ^- Q6 H" I! y; z3 `- f
if right.parent is None: 1 X9 Z6 I# j, }& d - o' y: K# Q& H: ~' K$ V self.root=right : T% S; f8 Z$ z else:5 F* D) f" t. m# u* `! e
if node==node.parent.right:/ A/ b9 ?. s1 L. L9 y8 L! S! W* c( o
node.parent.right=right 7 w4 G7 s' Z% D else:" o9 E$ R" Q/ O4 R! {
node.parent.left=right , v) ?1 V! u0 c( r$ u6 z3 L a: [. m node.parent =right/ d$ w/ J/ ` ~
: i" w+ a" x0 O* n% V. K / Z, h3 w6 `8 I+ S- k def rb_rotate_right(self,node): , ]4 T N! O2 d1 X* F left=node.left O& K! z: y U* W9 V9 Q, P! M0 p$ N node.left=left.right ( v) X5 Z6 O7 y 6 E* H" l1 n. i/ r& h if node.left is not None: ) v( F0 @7 R1 U% j2 E* O( h left.right.parent=node, _8 n/ e- W& R j5 `* W$ c8 Q
( f8 S: X- B! U1 {2 A
left.right=node9 C# |! t. s# Y7 S) H
left.parent=node.parent 6 M! ]4 t( U& ?; L8 x - a6 q/ ?) \9 v/ a if left.parent is None: * d: N( ?; ?: O3 r( s7 G self.root=left 1 i6 `& _/ a6 z! R2 Y& O: w else:/ G) g# ]5 `! {! R. S; @
if node==node.parent.right: , j' g, |) @; q/ _- `# l node.parent.right=left 9 m7 e8 W5 L* u) } else:5 [- o% H. ~" r+ f
node.parent.left=left 6 a- `3 p. Y2 N- A, p' U) V4 o/ o node.parent=left& Z+ O$ K9 O) v
$ q$ ]" \3 Y- N0 n/ g* P def rb_insert_rebalance(self,node):% A) n2 g+ j# C3 Z; M# ~ T0 X
parent=node.parent ) L: v" o5 c9 I; P+ f* j while parent and parent.color==RED:# _! l# a8 ]; Q! v
gparent = parent.parent ; H6 w+ R0 s$ K9 F" Y" f if parent==gparent.left:. c" e& @8 G+ R7 ]
uncle=gparent.right , h# N# _' J- v Y4 d! i p if uncle and uncle.color==RED: 5 p% P7 m, x* S9 \; n uncle.color=BLACK 3 D% \* o6 Q/ ?6 ^ parent.color=BLACK# R4 o9 G9 `4 W' |$ R4 h: d
gparent.color=RED/ m9 D. x/ }$ K( U% |9 g5 }
node=gparent! T4 a3 F0 [4 W1 j3 Z
else:+ z, r' |2 D5 v7 U
if parent.right==node: ! ?) |6 g/ H9 L5 t self.rb_rotate_left(parent) 0 x' l+ d V: e, Q1 z5 W tmp=parent : C' {- f: X+ Z* z" S parent=node" B$ d1 o/ V! l* V' V
node=tmp0 {. n6 P4 q+ P3 b- o# [
parent.color=BLACK # N0 K$ h) }: D4 o: [) F gparent.color=RED * H$ `0 L; U+ r; v5 n1 ~- d2 q; D6 y2 _
self.rb_rotate_right(gparent) 3 c' D. e2 i$ O $ }: l# m! y! p if uncle: $ J2 p6 a; k7 s8 b' v# Q if uncle.right: * W$ G! k2 P, j- m/ T& {+ ~+ H node=uncle.right 4 y" c8 `0 G B* L0 E else: # P0 M+ t9 v# R% C( v uncle=gparent.left0 N3 j/ N* h4 N5 l4 }
if uncle and uncle.color==RED: * J- @' b6 [( V7 `! ^; q4 i: q8 v uncle.color=BLACK1 q8 J) y+ h* B/ P
parent.color=BLACK: G' u( W T6 D& S
gparent.color=RED; ^8 d: H! O- I5 P+ f
node=gparent % P- l: y+ ]* h else:( `3 I* n8 f+ ~0 {9 K0 N3 s% H
if parent.left==node:! ?5 ]4 x; b i- }
self.rb_rotate_right(parent)1 y8 ^/ _$ R0 V
tmp=parent 8 Y9 W! p% z. X [/ V |: K4 @ parent=node 0 }$ ~* v6 L1 C( u; r7 ~ node=tmp/ a7 e0 `0 P! I& C) M( i6 z
parent.color=BLACK8 d6 _8 ^' B; F3 [0 b C: R( Y
gparent.color=RED & D* o* a x$ a, W, J% V/ L self.rb_rotate_left(gparent)7 e1 K8 x9 l# f5 K' z/ W; ]; q% h' @# |$ R
4 [3 \4 U3 i8 N4 P if uncle:$ |* ?0 x0 y/ @# D& N
if uncle.left: ) l6 X# x2 u: _% z- c node=uncle.left 9 }5 M, f7 J8 h6 K& Q2 _: P parent=node.parent 4 P6 ^" m- }; v+ \* ` 4 j% c8 z; ]& n7 w" e& s( Q L& G7 G& s$ o" i9 j+ n/ }: x
self.root.color=BLACK8 o3 @5 l$ e( r
# [& O# a& n6 A) v1 `0 L5 Q 1 Q/ P6 Q9 V$ W$ t4 Z: z1 T$ u def rb_search_auxiliary(self,node):' j( G6 E7 T+ \) M
tmp=self.root ! M7 y* W1 o! ~% F' h, W& I# _! K parent=None* M/ N$ {/ v" [! _' u! v
while tmp is not None:5 r" B$ M9 [* g0 N. C
parent=tmp u& D# M4 t7 g9 V7 l cmp=self.cmp(node,tmp)& [/ {4 y/ p" Q
if cmp<0: * [5 H, s) k/ h! m( I tmp=tmp.left 9 d( H4 S8 H" m else:9 I6 t- }+ G# c; w
if cmp>0:8 X4 A! x8 n5 n% ^$ ~5 u
tmp=tmp.right% l3 j- B. ?1 l
else: 8 j$ z5 M- t6 _" ?8 i return tmp,parent7 V/ _( Z' T5 ~0 y8 N( J
k# o" j) N4 u8 m
return None,parent" q# H0 V9 w5 ^! Z- A) Q& c5 O' F6 V
, b* |, s: H! x6 T def rb_insert(self,data): ' s5 _+ y* W; M tmp=None- V6 q2 r( M) U5 X. r
node=Node(data) + U$ ^, B/ R2 d3 \- l0 G tmp,parent=self.rb_search_auxiliary(node) ( l1 p: p3 E" r! K8 L$ y& a q) p3 o A' j; @, Q& D) ]8 ?& W
if tmp is not None:4 J: Z" |# d* d. n
return 2 Z9 L- O: ]$ p
6 [2 X( B7 C, @$ j. E node.parent =parent% F& T0 N) H' _4 `8 N) f# @( l$ k
node.left=node.right=None8 {0 t- L. J g7 G
node.color=RED' Q: E7 N2 B- C' J0 t
& `- ~! Y: W5 }0 z$ k if parent is not None: 0 L. R, Q$ ~, |$ B9 V: p 4 }; S4 V6 A/ b$ e) K if self.cmp(parent,node)>0: m" U/ t0 U$ Q4 H' S! f; Y
parent.left=node / n) ?) H4 k8 r+ Q7 z9 v% s9 O else: : ^& @* f5 y# N8 h0 P% u parent.right=node ! O7 `/ F: F5 h else:6 h( P7 _( K& ]* l% x
self.root=node 8 a7 W( t6 _4 S6 Y return self.rb_insert_rebalance(node) , a. z7 a$ w4 N$ x) P & X& i: [# L8 d; O& q6 y, M; W7 x def rb_erase_rebalance(self,node,parent): / N) r4 @4 a# M, ?; k while((node is None or node.color==BLACK)and node !=self.root): : x' d% I/ P$ q4 J+ P6 K7 j if parent.left==node: + _0 ]/ F( u' E. i7 h4 L other=parent.right5 X/ i/ `4 x6 G, X
if other.color==RED:& t9 k# t1 ~# m7 \+ U3 `
other.color=BALCK $ n' W/ K' k0 r- l parent.color=RED, X! M4 R% ]4 y; J& H6 q
self.rb_rotate_left(parent)- f6 ^ L6 r% j( ^* I
other=parent.right7 m$ G; c) N# T4 j
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color ==BLACK): # I4 ?9 ~2 G" V5 v7 E( k* [ other.color=RED3 O- p, w6 z* P
node=parent* d, i5 t: x: I4 u
parent=node.parent + y) ?4 Q4 n* l: Q7 m0 G& w8 u) N: Z else: , V# \1 e. {4 B# j if other.right is None or other.right.color==BLACK: ) @% y8 t& k/ F! _ + c, D1 e& m7 U- M- L, b# w+ e! `+ R5 r if other.left is not None: 3 J. m% E. S& V! m other.left.color=BLACK- t9 @5 w0 B6 e' {6 c
other.color=RED , s ]1 m4 n: c- h self.rb_rotate_right(other) % x* {3 b# T% T6 N other=parent.right, {) h; P3 h( x j, S3 D3 {4 ~* g3 j
9 F; p! a4 q7 O; y( W/ v other.color=parent.color % r! N) T, @) A* y- f0 y parent.color=BLACK ! X8 C v' [% m& I1 x0 p* Z if other.right is not None: ' K T e" [$ |+ J other.right.color=BLACK9 O2 a( A& |- j' r& \
self.rb_rotate_left(parent)) o9 U/ ]7 n/ E& h" i
node=self.root 5 i! x# E; `8 F4 t! x2 | break * T3 S- Q! R# k6 ` else: " j1 R% g0 j- }0 ^ other=parent.left2 D& Q' D5 e' U: _/ g9 m9 l" W
if other.color==RED:& L% O" v6 L1 {; J" x
other.color=BLACK! M2 z; M1 A0 L, X1 e% W/ q7 D: o
parent.color=RED - a! g3 Y. i6 }1 X" C self.rb_rotate_right(parent) ' U" {$ L& o! K; W. M3 V- M other=parent.left m' H1 A2 D3 @8 ^5 m" x9 I; E' n: H
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color==BLACK): ' b0 ?5 f, O) Q5 X" C other.color=RED+ L5 d1 X4 g" l3 [
node=parent5 e4 x+ ~# i i
parent=node.parent Z, S4 i, m4 r1 n& i% ? else: 2 a; g9 n- Z( W u if other.left is None or other.left.color==BLACK:) i- i, c8 @7 ]& u
if other.right is not None:" v/ c. u0 R P. x0 ~( T
other.right.color=BLACK9 m P1 J. L/ G% w5 }/ L9 p
' X& O1 t8 N: P( ~: i6 L other.color=RED. l6 T* L2 K; _2 ]1 `% l
self.rb_rotate_left(other) % Q8 A; k$ d7 G6 L; P# G% S other=parent.left9 ^8 {" G: A) l. |: x" t3 L" _
& u$ u# e6 i0 J! i w other.color=parent.color M/ @) I6 p( h5 Y# `; J9 a+ m( f/ R parent.color=BLACK % b% [( p7 V! p7 L2 Y; m 9 ~( y& N: ]$ n# y9 q- v# @ if other.left is not None: n% g# y. @* l1 b9 r' j# c other.left.color=BLACK/ K+ y" ?3 [9 G k1 C0 p6 C) R
/ s, O4 b0 H# G5 z% D- S self.rb_rotate_right(parent) ( d/ ]# x- T) p node=self.root& b8 n8 M* P T1 T, q+ p
break ) d- v3 K4 e1 P5 E* J0 B p0 n ' f% f0 a. Q# H9 G( J' g) V 2 P" }& q+ R' ]0 U 4 c) H8 M' w2 E0 U: e8 W2 I if node is not None:. A5 L" ^+ ]1 S- e
node.color=BLACK * i6 F8 I6 e$ c! L* M
3 X/ A9 C& o; \ E def rb_erase(self,data): 3 \* j$ w1 g! b* G/ d5 m( D tmp_node=Node(data) , H$ x1 q3 B/ U+ N2 V node,parent = self.rb_search_auxiliary(tmp_node) ; _3 K; R# n5 P% f9 ^( Z# _- K if node is None:0 e( d4 p" [& [5 W4 B
print "data is not exist." ( a/ d7 |" @0 ^: j8 b4 { return; U+ g8 r: c( ^5 a7 v; D
) v E! x) Y% s5 r: Y
old =node8 ^4 t5 m- S) F
if node.left and node.right: 8 M, b n* R$ \ node=node.right 3 }( O! N6 q) [ 9 }# g; X$ \+ E) D5 W' F% [ left=node.left6 V* {- O5 |1 X
while left is not None: & \8 m8 F7 |1 Z/ w, ^8 k) G node =left+ z0 F0 s4 o* P: I7 l8 N
left=node.left' `( V2 P3 C- w: H' d
& Q' l2 } h/ D( y# o' K6 s2 Q child=node.right 5 x& I) x+ t* H; W( x' h0 a! } parent=node.parent" X1 H' {: N) Z5 I, A4 x
color=node.color! Q+ |# ~ h# u/ Q! s8 K
- L9 s) t+ _' m& U( T# z
if child:& ?; O7 i- R# q) ]; v4 q
child.parent=parent 2 f& d( c0 F4 \2 x3 W5 ?5 q7 i if parent:; p$ X$ x- I" N1 R
if parent.left==node: i6 M) X; K. x! f parent.left=child 4 r, E" D: t7 l2 L else: }0 ?6 ~5 O8 Z
parent.right=child 5 Z; K! E2 g0 s F/ l" j# r6 d; `, ?
else: : N9 r5 C$ I7 V3 w( a% c self.root=child7 I: Y: ^: y/ W0 B/ b; z% W9 ]5 g
' M, z4 j. U e7 m. Q, g if node.parent==old: 7 } F- ?& B9 y% ], J5 D parent=node 4 x7 Y/ N$ R- ^/ c! v W, s node.parent=old.parent7 }6 e' M9 l6 n
node.color=old.color " y. d/ [2 E4 o1 R! q node.right=old.right 7 B+ l3 ~$ ^2 x) ]! d node.left=old.left- N1 x# m' a7 J& O; e
& [5 W* k p) R, `9 I2 v# Z: ^8 t8 ` if old.parent: 6 ]- T1 t" o% d1 I9 |3 Q; T, g if old.parent.left==old: $ i# G: [% G! g: T old.parent.left=node8 C, `8 E) ]3 N+ y/ ]4 j/ d1 v
else:6 n( l( a* s( r- }3 N5 b. Q# x# Q+ f
old.parent.right=node7 u+ w3 I4 @8 r- ?$ S
else: ) Y5 ? ?2 n7 b6 f3 n self.root=node # D5 ]6 V& ^& \ c) O/ j5 y/ c c4 k4 W' C7 Z( c) B
old.left.parent=node ' ~% g& b& Z! s& U if old.right:1 Y9 p. V5 d' W& `! @4 f$ X
old.right.parent=node6 z5 f& l$ s C: Z
0 _2 u/ }: Q( R
else: , F' j" L/ a: F9 l7 c6 D( v if node.left is None:6 B; Z" a* l: C7 x: p M/ l- ?
child =node.right0 i- u9 F7 o; S+ L# p' X
else: - M$ J* T3 g2 {# P if node.left is not None: 5 t6 C! M3 ]. V1 \, D( a/ d child=node.left/ b' Y1 C4 \" v7 E4 R4 g8 K
else:; L5 r: q% k, Y% x
child=None ( ?- Z) i. t- i0 p' \* q parent=node.parent / W& f. y/ z4 I( j+ @& K color=node.color 2 t5 R0 w, E% w4 l' C) ?6 x if child: & t& ?0 O2 e: y! E7 ]2 f# } child.parent=parent . v, P- J2 y5 D. i/ s if parent:: G6 x6 B5 F$ K! O" O- n
if parent.left==node: ( s; D. r0 q7 e- e' j5 \; l0 \ parent.left=child " O) q$ x" ~7 M6 i. d. j E' y else: I* ?8 p3 }( D
parent.right=child! y& [+ q7 y% b1 O
else: V( K5 e4 a1 x+ T5 k
self.root=child0 B" H2 b6 a3 s% F) O! `% ^% g
" M y; P3 V7 x1 N if color==BLACK:( k; v# O8 a4 T( [! p, _
; o2 ?+ p0 D* B. I, ~- \" [0 n! _
self.rb_erase_rebalance(child,parent): P% N0 L! n' I& ?* m, O2 |! o3 ^+ c
- E8 j2 A- K+ S% Z8 Z, c" y; v( a* g
def rb_travelse(self,node):) y z: ]" h0 _4 o2 a& k+ {4 L
if node is not None: 3 X7 Z9 O' F6 o+ t print str(node.data)+'\t'+str(node.color) ! {8 N& Z( i3 r* ?8 F) @ self.rb_travelse(node.left) 9 K$ B W R% K, v, c1 k if node.parent:$ Y. @0 A. M5 t! r8 }2 X+ X; G
if node.parent.color==0 and node.color==0:# g5 d0 Q3 i& H% B C: W
print "error"7 D6 w0 [3 ]: c+ p
return 3 H y( D' e8 _6 n& A# P$ o self.rb_travelse(node.right)+ z; r1 W) ]. Z4 x7 ^! P
if node.parent: 5 |5 u2 {6 r0 e0 \9 x/ z( O if node.parent.color==0 and node.color==0:+ ~& X' o: m. q. `
print "error" ) ~/ h/ Z6 F( g1 Q return" Z. v% Q& b9 P% D* z
# T* T \0 u3 R& _, P8 ~" U
return ' k1 V2 ?( I ]# r5 i8 w 0 d- z0 K9 u/ Y) V
* C& c& @, T/ |2 G8 W
def cmp(self,node1,node2):1 n$ g* \6 T% i
if node1.data>node2.data :8 S* e" j) i2 V# C
return 1 : f" A3 D- M* v1 U. v4 c% k) V if node1.data==node2.data :/ N" Y# c& [2 ], M
return 0( r7 y: ~4 r" s5 Q
if node1.data<node2.data: + ~4 @" A7 ?+ Y) w! h1 d, a! x return -1 ! {: n5 ]9 V2 e$ h 4 n5 R5 _, X& h Nif __name__=="__main__":" K9 Q8 u+ y9 m) t& z5 y3 E7 H
print "main" 2 l) Y* h; q: f! U5 d data=[28,6,39,78,6,43,61,56,71,38]4 S9 w+ Z$ y. T
#for i in range(10):9 K: u) E# r0 F% [1 e: p& }
# rand_num = random.randint(0, 100) * C+ {5 N* l) w# s # data.append(rand_num)2 G. T3 V/ s# D0 M v' S' H) J
#print data 0 v- z) e1 O7 A5 Y0 x t=RBtree()' S" Q$ `1 ]+ p' D8 {
" U! G/ b0 t b. b2 `1 ^0 d% Z) Y + x2 e5 g' L4 ` for i in range(10):/ x6 N) k; `' x/ L4 j
t.rb_insert(data[i])( G; z0 z9 x% ?0 C; o! J7 o
& `- _, B3 T$ `8 }6 k4 @6 K
( r! t9 a5 }+ a) h
t.rb_travelse(t.root)6 `1 W0 r o3 l# t, }, B) _
9 r" R9 g5 V# h9 Y0 l- v8 C! ^4 ~6 v
print "---------------------------------" , Z; V) z3 r! `9 N t.rb_erase(data[7]): _" a' u( S, @3 v N
$ m3 Z- x( B6 l& U- z t.rb_travelse(t.root) ) O. S/ E1 r! Z' T2 ?" P1 J. Q1 t Y+ ^5 w5 ]5 i' n