#!/usr/bin/env python 5 i, F9 X5 e$ d& V7 `+ W# -*- coding : utf-8 -*- 8 ^: K2 v* U- e0 D) C2 E( {5 ]+ T
import os & A: B. e4 F( D9 B" I9 Wimport random! s; G& }. b4 |/ e* i
: B6 y& f& w: V" o! Y8 fRED = 0. m2 g' K0 v; R
BLACK = 1 o5 y# E! z6 l; D
9 p8 V" Z% ^3 p$ u9 H1 Aclass Vector(object): # p0 f8 o7 n6 y9 P5 Z def __init__(self,x=None,y=None):" E# e7 P! X1 A: c3 d
self.x=x/ s8 a( x6 d# x y" t6 k. K$ e$ e
self.y=y 4 G' I' K- Q0 ~* z& W* \: C 6 x8 x' H$ o& L4 aclass Node(object):. p; ~9 }% w5 t e' z' k) g
"""docstring for Node""" ; A* Y( F3 y4 U- h; l( C9 [ def __init__(self,data=None,color=RED,left=None,right=None,parent=None):3 ^( a/ G" d8 k$ ^& k5 p; _
self.data = data- Y& k# _7 b1 R5 b. I4 x7 A# O
self.color = color 7 N$ Y$ T5 |* w: Q8 j self.left = left% h" z$ I- ?& q8 v# i2 @
self.right = right3 E1 B7 g# c2 t W: N
self.parent = parent1 b% C* G5 J9 R @
( f4 t8 e9 M) F$ ]8 X7 Y& d$ {) b4 D+ U7 Sclass RBtree(object): ! g' Q- L5 t9 V8 X; ~' g/ Y def __init__(self):- @5 X6 i. F% m) W8 {$ m
self.root=None: b i# G/ f2 R# r' j# Z
self.size=0 3 N; B( b" y5 J ( m/ m3 k6 N$ z def rb_rotate_left(self,node): : G) B- u4 j5 J, D1 B+ K' h$ j$ K right=node.right , F$ Y V2 @/ ]$ s% d7 i; i+ V$ E. Y
node.right=right.left e2 y4 F# n# `5 A8 w
if node.right is not None:3 Z, G6 R1 N1 v* ?& h) H& [2 I
right.left.parent=node) j# c* }# o: q: z8 L" h
8 U6 ^4 z! J& I* G- e& E7 i
right.left=node 8 h) }- T6 i" [! L' W: z right.parent=node.parent $ H. F {2 p$ W6 r- D% d* e 9 Y. y% l) `, m' s# D if right.parent is None: + |& |; C9 Q. ~0 D0 U1 ] - I2 P. X/ m$ c# \, e" E- i% y self.root=right & M8 V# V7 f) t7 E else: 5 Y K8 u+ u( B! W% T& p6 @) a' A if node==node.parent.right: . J' l8 ~) q7 \+ }- [' t h U node.parent.right=right $ p0 g! |6 \ F: d# e3 ?5 H else: + p; z6 }% v2 s node.parent.left=right : q& `2 v; C- x; z d/ \( n node.parent =right* g! c- U8 ?& @3 O3 A
% v! N' {, h9 u6 z) e! H+ f
3 a& F/ X- P7 o
def rb_rotate_right(self,node): * T% K4 o3 }; ^ left=node.left4 t# {8 P8 q7 m6 O
node.left=left.right & y; K. r: j$ n* r8 H+ n1 `3 m+ o
if node.left is not None: 9 b6 D# l0 I& n) F4 E: f left.right.parent=node $ i+ H; [: o1 S, z) } : ]( D4 c2 k3 O. S. u- b# c( d1 y) I left.right=node 0 F' f3 b0 q: e# u: V left.parent=node.parent; E) I5 c- p M( p4 \% N
6 j. N V( W, ?( u2 h8 W6 U if left.parent is None:$ z; P$ ]0 k8 Z' r* d9 i7 @
self.root=left - n9 n: q% @; |6 t3 H& R else:1 m; e4 F' S. L9 `- b _2 m) N" W
if node==node.parent.right: ! b: N8 l1 |* s) l2 R node.parent.right=left6 K* Z; J% I. D' k3 l. w9 E+ t, O2 @
else: & Q0 S/ ~3 k5 _2 s node.parent.left=left5 y! d5 z g% g3 ]6 h& C
node.parent=left 2 N. k, s4 ~. k S- F1 M3 F, p. Y4 I6 F. u$ @0 l( l9 q: P; E; m' o
def rb_insert_rebalance(self,node): ' H& @) D3 `; @( w$ t3 R5 N parent=node.parent9 @ l7 w* h2 c5 [% j
while parent and parent.color==RED:1 x0 ~% @5 r+ i, B" c
gparent = parent.parent; O) n* }7 b6 R. R& S. m8 G4 l
if parent==gparent.left: ^; j8 i& T- C$ e! t& R. b% x$ J Y
uncle=gparent.right( `6 ]) N/ y5 |( I/ i& Z! K1 k8 |: O
if uncle and uncle.color==RED: ) I1 F q3 v8 _. A$ k uncle.color=BLACK' c1 ]" B" k% ^; x
parent.color=BLACK " e' ?( U4 ?& F& Q gparent.color=RED1 `6 V; |: B& E+ f$ Z q
node=gparent5 [4 U; m" q) ]
else:3 H6 X. Q& B; V) R4 a
if parent.right==node:5 @! T- |1 Z. O" O- _
self.rb_rotate_left(parent) 8 t* I3 y. y* | tmp=parent6 k& F) O6 `. J( ]" y, m: z
parent=node6 q. |/ J$ [6 L ?% \! c( x
node=tmp3 B3 T& [8 w$ A2 _$ q* c9 J0 q
parent.color=BLACK6 k1 g* i: B" n; j, x, u' x# Z8 S
gparent.color=RED & Q- G6 B3 |& B1 q2 X. ~3 o 5 r# S$ _4 ?) q6 q0 d) i self.rb_rotate_right(gparent)$ _ v6 Z1 x& m f0 M; A
8 U& d. u u5 |- S2 v% f9 j4 i if uncle:% r" I; C) q! T
if uncle.right:" e& J$ d/ E+ e/ r# f) `' ?
node=uncle.right# s+ \5 m/ o0 @; Y
else: 8 {. _ @3 k o) q6 { uncle=gparent.left 1 e% @/ B7 B3 n: ?7 c if uncle and uncle.color==RED: , G' ~; H- L0 b( s0 a# i8 Q) e& W uncle.color=BLACK ( F6 j! w- _% b( f8 l) C( @2 t parent.color=BLACK . f! l8 [5 w% z: a gparent.color=RED 8 I9 k* e* e" \4 M) ]- [ node=gparent' J, d3 ^5 d, U$ x2 U% v0 d4 u
else:" ]# g2 z" Q' ^6 D" H8 Y
if parent.left==node:/ z& M; O8 ]" V8 B/ G
self.rb_rotate_right(parent)6 }& Z3 [* V" e$ ]3 T# t2 a
tmp=parent: o6 L; {4 J. F. J+ h: B. i2 f9 F
parent=node6 U; P9 \1 H0 F4 _2 V, e1 ]) z
node=tmp/ K$ J4 r* u2 v/ @
parent.color=BLACK M' S9 M/ D# b
gparent.color=RED( n7 l3 N3 a' m/ ~8 \7 L
self.rb_rotate_left(gparent); x e: j0 Q+ l2 N
( a3 W8 R0 w! p( u- J, S* Y& K if uncle: 3 m( [* b' r+ Y1 A$ \. h5 _2 j if uncle.left:; X% ~1 E/ l5 Y7 d
node=uncle.left( @) C7 n0 R( t& x
parent=node.parent S4 [/ F. I3 }* ~0 J9 [, F9 ~ 4 F+ P- {( O' a! }/ I5 i. A 9 a8 G. `1 t( _% m1 C9 C self.root.color=BLACK 1 ~7 Z# n( a0 d2 p 8 I5 o3 j6 z4 A0 v6 t; T
& m; @) d; }1 g: V9 ?! Q def rb_search_auxiliary(self,node): 1 N' O% z. A( G2 C6 {! X tmp=self.root4 Q; @( O" x q' n6 N
parent=None$ Y; L2 U7 R" E+ h9 t5 P2 j! }
while tmp is not None: 1 A. N. R$ Y; Q% |1 J parent=tmp3 [9 |$ O& `; q* k- E3 \2 X n
cmp=self.cmp(node,tmp) }. q5 O1 Z$ I5 L8 V& J if cmp<0: ) i& z+ @0 e# b/ h tmp=tmp.left6 ^- S- K7 \7 ]: B" R
else: ; e3 p7 u, }% K* e$ O if cmp>0: m8 ^9 T( F' P5 \3 J) ?" E tmp=tmp.right- S) L; Z: }+ }
else:$ m+ c* z$ c% E5 X
return tmp,parent 9 ?8 H! o- Z& q" M8 f/ T& Z2 B8 T $ _+ f% O2 q+ s q1 z return None,parent. n9 R0 J$ X5 e( V2 W; @" o
+ ?; r2 L# h' ?/ Z0 q def rb_insert(self,data):- C- V9 I2 @6 A% S7 D
tmp=None9 n0 g* m* t* c9 g/ Y/ o! X( o
node=Node(data)2 x/ p* v- i4 _+ x
tmp,parent=self.rb_search_auxiliary(node)+ L1 |) n% g8 ^' i( d
/ `+ x8 ?! P* R
if tmp is not None:+ `! q5 t7 E. r( k% n1 v
return 3 ?; k; D. |# A8 T ) v, y e+ m3 z$ ^0 R: ~$ ] node.parent =parent " |% l ]$ u. ?1 g5 j1 X$ i node.left=node.right=None " |8 v" P% u7 } Y node.color=RED $ y# d0 C5 g3 o( I" r3 o% k0 E5 M! H- A* R0 G! a
if parent is not None: 9 Y1 ~, g2 L6 g/ c1 ~; D ' I- q4 U; w4 g0 [2 p if self.cmp(parent,node)>0:: @) W+ w; ^. l
parent.left=node: H6 {" K" J2 }) E$ n [
else:+ ~$ B: C2 a4 ]; u4 g
parent.right=node 3 A, }' d- C o) z: A else:* H9 S1 |- y% u/ S7 M. u
self.root=node ( M' o1 T7 |- r return self.rb_insert_rebalance(node)& j/ p) M' h/ R5 N$ \
* n7 b) ~9 J2 L def rb_erase_rebalance(self,node,parent):: Z) u# v% L4 p5 V [
while((node is None or node.color==BLACK)and node !=self.root):/ U! J+ k8 \9 s! ~% @+ {8 |/ {/ H8 C% ^
if parent.left==node: / T8 [5 Q+ h5 l& w. U/ Z R other=parent.right 1 C% o o- F8 e3 p( Q# K1 N if other.color==RED: n# c4 P* i, n ?5 g
other.color=BALCK- S( h9 w+ Z; u ?6 r
parent.color=RED # S; _4 H E3 ]' J2 U0 z self.rb_rotate_left(parent) 5 M, d9 }( s: R. ^4 s) K5 _! w other=parent.right " t3 z$ U$ Y! j' l if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color ==BLACK):2 L6 a- W' l4 C7 j: }, B
other.color=RED! _- e4 m. K( b1 M5 k
node=parent & I2 j" }' Q5 Y f( ] parent=node.parent 0 i. I& l% T: b5 Y1 n" s/ K else: , B, z9 N; p$ }( h9 h5 [+ P2 _8 j if other.right is None or other.right.color==BLACK:" O& y+ g' J% c5 e
1 y% B# X: _1 C$ B0 g9 g6 c( r if other.left is not None:& m) n, n4 O/ \2 v9 K6 t7 D
other.left.color=BLACK . H) \- I0 x$ I, @6 z other.color=RED ' D8 @. m$ I! B+ `; ~ self.rb_rotate_right(other)" z+ u& `8 p! s" J: v7 q1 s
other=parent.right " ~# l: {& Y: @* j! e9 O5 C: H$ |+ f& I) G! j! B9 m: f
other.color=parent.color* `* }: R1 d' _ l
parent.color=BLACK * H/ a0 {' \' a if other.right is not None:& m+ z* \; z$ G2 [0 d4 |
other.right.color=BLACK# {5 X9 F: h" L4 _
self.rb_rotate_left(parent) % [2 E# B+ t0 ~/ \+ F! R# J- D node=self.root ! _ X9 A1 n. P break% z0 L7 W) b+ a
else: - X& h5 e5 Q$ x# U) ] other=parent.left : p0 B9 C% w% n0 N2 |0 _" L if other.color==RED:( s- o# P- b& c" b* ?8 D2 T- {& P+ Q
other.color=BLACK ]1 b" t0 l2 x parent.color=RED. k$ g5 Z+ u0 v
self.rb_rotate_right(parent) 7 l! ~2 T" X# _, e' d& B9 j other=parent.left9 M) Z1 ~3 K3 X& I5 u+ t
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color==BLACK): 9 [5 g% f( ]3 h( c# q7 l other.color=RED, M+ f. m& N/ k9 x
node=parent * Q H' Z1 ^' r& s9 _ parent=node.parent 4 X; u, d3 I( W8 [8 A( Q else: 3 F# Y- Y" I; Y( w6 t/ i if other.left is None or other.left.color==BLACK: . @: P* y ^0 }0 l2 j+ D. M& f if other.right is not None: ! p1 D! I- X* d- U( M other.right.color=BLACK3 v& u$ o& _+ Z% x7 k
9 y; ~; t4 a/ M0 N, D. v V other.color=RED 2 `7 _3 w: E0 ^/ t( r$ C+ R! O1 E self.rb_rotate_left(other)/ C( u- j4 `; t$ _( f8 K
other=parent.left# I2 |9 n9 q& n0 y/ u/ O& M
* W# t3 W; b9 W" f8 t+ J1 Y1 T+ I
other.color=parent.color+ X7 h6 P2 p% B7 A6 U; u/ U
parent.color=BLACK1 `6 [/ q0 ]. M3 q d% F5 T
$ K, E1 B1 M- I: }/ X$ e) O# @0 }
if other.left is not None: $ j& s, E9 D* V other.left.color=BLACK1 {7 M t7 L" O1 X8 q7 Z
% I( `$ W+ S6 X, s0 E
self.rb_rotate_right(parent)$ `) i+ `, b& V$ v8 ?
node=self.root 9 s( n- l3 d" H* S% e" s. u break& K ^1 }; L+ o- \* T0 W' v! L1 t
" o& J% L: j5 L6 q- w- P! M# z , Q5 H3 X. X/ p' l+ l 7 D' C8 O+ [ |( ] q if node is not None: ! B6 [+ d$ @- k9 d9 L/ y( ?7 G node.color=BLACK 9 G1 K1 K1 T- m % A2 U$ l. Y" }$ _+ W% Y def rb_erase(self,data): & z) H' m; v3 U tmp_node=Node(data)! E0 v" L' v: v5 Q+ Y8 z* _2 J* J
node,parent = self.rb_search_auxiliary(tmp_node)) y' L5 F& }8 |# l2 p7 F
if node is None:+ ?* N& R$ ~' C' q8 |; V- y
print "data is not exist."" y( X! j9 Y) P
return 1 d( C7 [# d; Y. M) s( t6 \ ( c6 Q$ ?7 z4 i. ?* e old =node 0 X. b0 G) ^6 a" M if node.left and node.right:. c. k# h& S, Q6 V7 N
node=node.right" J. v4 L5 C6 p- V
# I$ c% J. E( F' K
left=node.left 9 N1 S( I5 F; Z+ W7 [! X: J while left is not None:9 i0 b) t( q9 [, M5 `
node =left O& Z& R0 t9 o: a- Y1 T left=node.left: [1 r$ Z* g: t9 S
, P9 q1 ^. I! I; t( E& b
child=node.right8 {4 g. N3 O a1 G5 J
parent=node.parent# A+ C/ b Z' C! b
color=node.color: |5 l; O: }; M; W" l* I; B
: I+ h; B3 W, C+ W; H
if child:, |5 K A& F5 [2 c) }/ s& W
child.parent=parent* r' g' r& s2 B- f9 y
if parent: ) z/ R8 E j& b' E6 N# f/ e& P$ ^ if parent.left==node: 7 G" `( p* b& i parent.left=child" m) c; e( I. a$ ^' f: P+ }
else:: J$ q* M+ l# S# a2 w
parent.right=child 6 e* S* t D( w& B6 w7 s5 H4 }2 |; {+ b/ R+ I
else: 6 U3 Y* x" P' |( @ self.root=child & Z5 `: ?8 |# H' W1 j ; F$ ^3 o: l2 u6 M4 t7 B8 V4 { if node.parent==old: , E( c) \. k. G6 _/ u parent=node ) L, B" h F! ~* _+ G node.parent=old.parent % v4 m: R( _' @1 X0 _7 Q, @- C node.color=old.color " p. i. n% ] J- T) C8 e1 o node.right=old.right & j7 u4 j6 Z. s+ Q node.left=old.left 7 s/ W; S) a7 V5 t3 e% ?1 D& K8 g" }9 Y/ ?
if old.parent: k; @# W* R+ x( k z4 e; r- R if old.parent.left==old: A, g" ?- E' @ old.parent.left=node4 N, W" g C! g6 y, v' p( `0 Y& \( c
else:7 O7 J7 l3 [2 i' m
old.parent.right=node 8 C9 {( @' b8 V, f else:; m0 ^9 M& Q" r9 o* O
self.root=node! b# S: C w9 s1 C' ]
( o; X2 ]7 _, p V* W/ z5 L: v
old.left.parent=node `$ a6 F: j1 V. c5 G" q if old.right: 6 v/ M2 Z$ E' Q$ @5 q: g- [( j9 v3 G old.right.parent=node b4 w- W! n. F, x6 `0 z* ?* y4 `/ {2 y/ N
else:0 L3 K9 _# @6 h7 r/ t$ a3 M
if node.left is None:+ d2 M' m$ W- d, r( y E
child =node.right n$ B! P- |# x& h! L
else:+ v; f# p) E5 [0 ?
if node.left is not None:7 b. A) O1 D7 n
child=node.left" H$ O9 X# h% }
else:& i& A. b+ G# g+ q/ g+ b
child=None 9 y5 N, U- y! o, w" C0 L, x* Z- g parent=node.parent % j6 H7 P* G( |1 C color=node.color . V7 t: N z* f. h6 i3 a if child: 4 d0 D z% f9 R( Z7 N& _8 z2 ? child.parent=parent, P& ?2 G' K5 q
if parent:* Y' v/ D; M) ]$ g1 w. Z
if parent.left==node: ! G( M: U0 z/ E9 F parent.left=child 8 @: [) Z6 M6 |& K c: X else: ! \% h# N0 c1 v# @5 r parent.right=child/ t9 n* D; N5 ^' }
else:2 k- ]# S0 d' ^) M
self.root=child. r9 I# P5 [% C1 j& O1 y
6 c( V/ I- j+ i( L# J9 E- h; j6 _. c if color==BLACK: 0 W" D' S1 m$ l* _ h; B2 o8 G* I* l self.rb_erase_rebalance(child,parent) 6 ?: V: T3 M6 ?* I9 \; G0 \9 ~/ }! N: z7 N% \
6 O( ?: O& o. g& U
def rb_travelse(self,node): k" I; L6 \0 [# Q3 R if node is not None: . k l& U, h F print str(node.data)+'\t'+str(node.color) 4 o! n( @ t; H: x2 t+ I" Z self.rb_travelse(node.left)$ J4 {+ l: @* Q- Y
if node.parent:9 p2 ]' Y! }1 e! X: }
if node.parent.color==0 and node.color==0:; e) ^* J& F& Y& m, K
print "error" / a7 {% R* H" X3 k* H) N return, @9 x; ?2 P/ b, Y# v9 C
self.rb_travelse(node.right)8 S+ w/ ? g6 b6 m
if node.parent:- B' N, `( t. w) i0 P
if node.parent.color==0 and node.color==0: 1 I, p3 k/ S; J7 Y- n: t+ J3 C print "error" . c; W! Q+ P) \0 e w( w2 M1 [ return / s y3 w% M: \( t. f4 j 4 y' Y+ K7 |8 x! k6 w, `+ c( s return ! L/ ^( |% A- a; l6 x ) J. n5 D, c* q/ u& s) s1 Z0 r
! y- N0 n3 \+ U: S% ]0 s, S! M% b def cmp(self,node1,node2): ) K5 h7 {( [7 D5 ^6 C if node1.data>node2.data : 3 h" b7 M! H! |& l return 17 N6 P. K% i' D" o, D8 j
if node1.data==node2.data : g; O4 m& g0 s8 t return 0 ; o% m& }6 F$ `' T6 u* [' `/ h* ], J if node1.data<node2.data: 7 k! O5 M) q) u return -1* C, S8 g. d T! x1 l# Z
+ v! e( R" W5 ~/ b( Wif __name__=="__main__": * Z! y' h+ G8 Q3 o$ G, c8 r( G; w print "main" $ l4 ?3 V5 U+ b# S& S data=[28,6,39,78,6,43,61,56,71,38] X/ \, R+ E# z- }( n
#for i in range(10):5 v2 e# ~- M5 m7 e6 ?( i: V
# rand_num = random.randint(0, 100)5 {. z7 k* W t5 [) H$ A
# data.append(rand_num) 5 L6 y8 T" P8 B K, ]8 D #print data 6 q7 }: z! c7 Z7 k( d9 z t=RBtree() % g# d% h# Q5 J: m : \* d+ {0 }2 W+ Z6 X ) q W8 v) m6 o8 k8 R for i in range(10): ! z y$ O/ M9 V% h- G t.rb_insert(data[i]) 9 y# L7 \6 `8 _( I ! U- q% E8 B. q t6 ]1 g7 d- I4 w2 _% j- A
t.rb_travelse(t.root) : H, M9 C1 x8 I9 y6 B1 G# D8 n$ G# E2 n+ ?
print "---------------------------------"1 m* ~" v$ k3 }- y1 J2 ^
t.rb_erase(data[7]); w& O' s6 o0 v1 D! j; Q
9 i6 h, n B9 C, R4 I
t.rb_travelse(t.root) % H- Y+ b4 J2 I# @! m7 @# J# G: Y. a, ~( L