#!/usr/bin/env python4 e* Z7 w( @ G7 d- j; x
# -*- coding : utf-8 -*-/ @% L: l/ @2 x+ K+ G1 w
7 R5 h4 k4 U; m& H7 E. A. h+ z
import os3 d- f% S1 Q C
import random ) _5 O& m5 }" e+ t7 x- c- y- {; i$ ]* ]: d3 Q2 F( m* ]/ |- E
RED = 0% Q: t3 o g! X! P
BLACK = 1 % F( b* {+ V; p- F1 Y, L0 q, I: o # G# n- i3 u5 P j9 `& E8 oclass Vector(object): 4 O1 h* W0 E; c: T# d- ? def __init__(self,x=None,y=None): - G& H6 G1 O+ R* N; g self.x=x2 Z0 s; e: h- ~- F. _3 E) h
self.y=y ' \' l, V8 t0 a% i. v " ?* I. T7 k: y+ k. Gclass Node(object): - O# J p& a3 Q+ g* M0 F9 l """docstring for Node""" 1 ^9 K; K! T1 b* R def __init__(self,data=None,color=RED,left=None,right=None,parent=None):5 H" k6 }0 u7 }' r, n m% u7 v
self.data = data4 ^/ z+ d1 _1 h+ e0 c8 v- S
self.color = color' @, N, U& [( Q. _' P; t
self.left = left 8 Q. l! S4 j0 w+ P self.right = right " x# T* m: B- d self.parent = parent 0 S) `8 H& Y5 S! [ 0 [. x- p- N# r& |class RBtree(object):, _( I" ^+ l6 H
def __init__(self):. \0 z3 O f. Q8 Q5 \6 C0 S2 _, y
self.root=None4 m0 B/ Q. U) I' a& p( u, m$ T
self.size=0 $ O# T. ]: M" `$ G" i% u; f- h7 A, G# Q/ R$ d$ u! o+ L' ?" A
def rb_rotate_left(self,node):& w# ?9 B/ q1 F/ h" |1 ~5 D
right=node.right 1 ]( a5 P" r3 `5 n* T% g! L, s# V1 k2 w) o
node.right=right.left: m; I) V. v$ t2 }& x/ v! \
if node.right is not None: 8 P) n) X* U2 t; ? right.left.parent=node9 L1 e) l8 k P& A/ e+ `( v& O. t5 c
1 \" l( @! u- G# g% l6 w( L0 K; M
right.left=node ! M% W' F( V4 i) I: v9 ~1 j3 k2 M right.parent=node.parent/ D/ c4 s5 c# j( i- q! S5 v
; @" E3 E- o$ R. g; ~! j8 Y if right.parent is None:4 J( L. w5 w# }- R
* F' c/ K3 U3 ]# [, k
self.root=right 1 b' U; R. F9 f else: : y9 E9 A: Q8 w if node==node.parent.right: 2 F# c& V3 \$ K* r! r9 w1 d- v node.parent.right=right- G; @! @# ]0 K# ^
else:$ @3 [: _, q, @- R3 }
node.parent.left=right( v' s+ k# `3 [$ N J8 ?
node.parent =right . Y7 P5 j$ ?5 q0 v " Z5 M7 M% W9 p1 c. W6 _% G2 k3 x# |. E/ F# z9 t( a
def rb_rotate_right(self,node):' F( K) }/ _& Q1 K+ D6 k
left=node.left 1 |: L( u1 S9 i1 a! ]. F node.left=left.right Z3 ]. ]$ S! `3 A {& |1 u
) e* n, Q' Y0 v. P) B) J8 y1 M
if node.left is not None:* Y2 W( X3 C2 T W; B; r
left.right.parent=node % t* L) l) `& m* J6 T' Z6 b" s$ b2 q- s
left.right=node9 v0 y8 v N) i1 ?# b
left.parent=node.parent0 Z8 j! |4 A! G) U) |) W
. Q4 Z" ~# z; X, j3 W if left.parent is None: 6 P+ |' w7 E8 O! E9 L self.root=left+ U4 c9 w; {& r# K& Z" L7 t
else: x" N; u, Q% `; [6 D if node==node.parent.right: - N6 X& I! {/ t3 F. _& u/ \' |' ^ node.parent.right=left- h- C* y0 p' h7 _' p1 D7 {
else: 3 V! L/ E: ^! K+ P+ g node.parent.left=left. K1 [3 \$ L x8 C$ r+ E
node.parent=left8 T* A. M6 I [% m9 [
: a* m& C4 v0 s; \# I
def rb_insert_rebalance(self,node): . T+ k. e# R: r/ c) @ parent=node.parent ) P9 W- q) K3 p: |* h2 Z- P while parent and parent.color==RED:4 V4 J$ g5 Y5 `# ?) }9 F9 H
gparent = parent.parent 4 [( |( Q1 E+ `: M9 |$ M: w if parent==gparent.left: " q ?3 ~4 b; s: Y" u5 M uncle=gparent.right* b4 U) u0 q' ]- Q, s* |
if uncle and uncle.color==RED: 0 `7 s% B) J. ~/ { uncle.color=BLACK: E a% k1 \) \7 S% m' |; W9 X! K
parent.color=BLACK . R/ J7 W" w4 j' q# f3 K gparent.color=RED 7 v6 H7 o; C/ k; u node=gparent' o' M& V- B- y4 i3 z& _" c
else: + m& Q/ M6 o7 m! e! K. c if parent.right==node:. r) y" b! d+ M
self.rb_rotate_left(parent)* \* s) ?2 \1 ?8 r, a5 b! M
tmp=parent $ @- {/ ~- X5 r' L4 _ parent=node " w0 ]6 @1 ? j% O! x node=tmp $ ?7 W# r- j" {4 b: V parent.color=BLACK! D7 J1 m& o: Z( l
gparent.color=RED1 ]; R' S- a5 ~% G: Q5 C# Y. u" T
' N" B" d' u+ Z+ m& O* w
self.rb_rotate_right(gparent)% [7 h. P z$ E/ H* y9 W) S4 |# y' t
6 k# j' Z* D; k: { if uncle: # e/ G9 h. a; Z+ r if uncle.right: : w( g7 f7 y/ U! l9 q0 \3 j node=uncle.right9 d, v) d/ X' m5 A
else: 0 r& d, v- H1 ?* l% q uncle=gparent.left ) }7 u0 P0 J% n2 \0 t if uncle and uncle.color==RED:3 D$ N* ~1 T9 K
uncle.color=BLACK* S, c# [( J6 q
parent.color=BLACK' U+ p b( v4 e
gparent.color=RED1 D, W0 W n ~- s9 t
node=gparent' S0 [# n& l* t' l0 Y2 u
else:9 R- v% S3 F. u3 s. E
if parent.left==node:8 W4 \; t7 V9 A! @- \! J/ K
self.rb_rotate_right(parent) / m7 V/ d$ {( G tmp=parent . j2 \3 {1 y0 a' [, U; f parent=node/ D( D0 G, e/ ]
node=tmp3 }6 S4 j7 A& w3 f2 \1 a1 Y# v
parent.color=BLACK 4 |( g' k1 a) ?$ ^* T gparent.color=RED & {: v: c" K& V8 r8 Q8 h self.rb_rotate_left(gparent)7 @# R* ]) f1 N7 l
, U+ \+ ?( b; P; h' |" |) J
if uncle:' j* ?4 i! ~3 A2 V2 \+ x
if uncle.left: ( M& T$ w2 p: J1 }6 [% W! k node=uncle.left7 h) i' z1 {# t5 ~1 j
parent=node.parent $ H: t! ^" A" c 3 T% m+ X% {9 M- Z& L" Q & d3 A* A8 s9 j! v+ \- l self.root.color=BLACK# Z; ^3 }1 W. F: L
0 B' D1 H6 t4 D+ H 7 z, i9 g4 o0 o' W/ p t
def rb_search_auxiliary(self,node):8 k! F% l% }7 p1 o$ z
tmp=self.root 4 A0 f/ L$ m& u. q parent=None( [0 b, X k) k) ?7 ]+ f
while tmp is not None: 0 k9 R* O E$ N parent=tmp. }( u" c7 p# o+ Y# m( B
cmp=self.cmp(node,tmp) - c( B5 v" x% L9 G1 Z# ]9 e if cmp<0: 2 e, _# g) K& q1 O6 P tmp=tmp.left ( n/ g( M3 b( P5 M else: , e4 Z3 |7 D# x, f7 p* c" | if cmp>0:% m3 Q) c9 v/ X, _5 Y1 c0 \8 n
tmp=tmp.right4 U$ c+ d; G- I& X' l, D
else:2 i/ c- X0 r. `6 P
return tmp,parent : B% ], ^& @4 W6 V, Z0 n3 m0 ]" w$ o L c% i5 _3 E
return None,parent8 E3 X6 T: f- i& t/ v% b$ s. t
; M5 t4 d. y- X2 k0 k+ U% @9 G
def rb_insert(self,data): 0 I' ~- R2 k6 `+ ` D tmp=None , g% ~# ]3 M) D node=Node(data) 3 u0 |# u! k r3 u8 H tmp,parent=self.rb_search_auxiliary(node). j3 k+ S8 M0 i' X) L& S1 V/ s
7 I8 x7 X3 v: s" C# `
if tmp is not None:& u) \! r! _# C1 w _5 Q
return 9 i* l( D9 R1 Y' ]8 `
$ j8 A) B* k3 ]% t: c; z$ }) x node.parent =parent 0 Q' ~' J! G4 o$ j3 M" n. x/ {# k' R node.left=node.right=None - o1 \) h/ u; z+ j. S. y! \: @ node.color=RED # F% `8 L2 d n2 C7 f' K9 d% N5 b; [; K2 k6 @
if parent is not None: ) S O& \& t& w o# }' P3 E, F4 n/ C& T* x- F( H
if self.cmp(parent,node)>0:0 o0 h) {2 ?' }+ c, |. z, v
parent.left=node& B5 b6 i9 u0 v
else: . p) v' T* E- A- w" B0 S/ T! g8 o parent.right=node- o6 v* q4 @2 z
else:, F& t) g: s1 J7 v2 c" H4 I
self.root=node & U! U3 Q, A9 d9 j return self.rb_insert_rebalance(node)7 ^& F& H- R h, a }8 f( ^
) i% I3 q3 [+ ^4 ^6 [ def rb_erase_rebalance(self,node,parent):! P, z/ V. h3 z
while((node is None or node.color==BLACK)and node !=self.root):; S5 P) l9 }+ Y! m$ _9 X( r) O. o
if parent.left==node: - p; ^% w; y6 N) `4 y9 h other=parent.right6 C3 x: K4 ]; r f; |, f
if other.color==RED: a2 G8 t/ Y- X9 I% H other.color=BALCK ! y/ |$ Y: H, t. ~ parent.color=RED 7 F+ k7 P7 R. A4 U% X! ~5 a5 g self.rb_rotate_left(parent)/ w5 I: @/ E" F0 w$ u0 @
other=parent.right3 l, C, a, p# d+ o5 L8 k
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color ==BLACK): ; `5 n+ R. B3 j& ~3 v3 Q- u7 V# z other.color=RED1 E5 N6 _( \6 A: d; k0 B; g
node=parent 2 n& w+ z1 _1 q parent=node.parent # R3 Y. V8 H, k8 G6 ] else: , p3 X8 C4 R5 h( ]) W. Z- a. O if other.right is None or other.right.color==BLACK:- V( \( \ C, a+ z8 s$ x/ r$ E3 Y
6 P6 `; A, m$ w" X, V4 E& |9 [3 y
if other.left is not None: " t) j' R& L/ ]$ f- M- o; u other.left.color=BLACK * y9 R7 w, ~4 V5 u other.color=RED3 u4 d; _1 ?/ a2 V7 f( S
self.rb_rotate_right(other); J8 Z, `' g9 d8 g6 X1 }7 w
other=parent.right2 E+ e L; s$ U+ Y
2 x2 }3 t# m: d! H3 {' u other.color=parent.color" T5 Y% T& T6 ?; B# L
parent.color=BLACK* l, x7 Z: b/ \ [' l1 a
if other.right is not None: 1 T5 n; @3 g* [& L0 d! s+ l! F. p other.right.color=BLACK * G8 o: q0 E5 Y6 \. R' q2 X N, L self.rb_rotate_left(parent) I3 D/ Y5 n1 c V* Z. U, h! l( D, B+ v- a
node=self.root" A$ }3 S7 h4 D7 \0 I/ O) _
break / w5 X9 Z, i& m( C' p" b# B( Y" a else:+ k4 |7 W7 A& I- j5 H, Y5 s
other=parent.left 9 j1 Z) P5 j8 ?2 J2 j8 z$ x if other.color==RED:& Y$ o5 E. g* ^" b
other.color=BLACK8 P) L e& d% s2 {, O# I
parent.color=RED , j. M$ q3 V/ s. j4 P self.rb_rotate_right(parent) 7 F) w4 u, g; O6 Q other=parent.left! t4 `. t! O! U4 s5 W
if (other.left is None or other.left.color==BLACK) and (other.right is None or other.right.color==BLACK): . \/ S. s/ Y' w! }4 N other.color=RED 1 E% f' a) B( F4 ~ node=parent3 l2 h5 j& l6 r0 f* o6 d* Q: K
parent=node.parent ; T2 d5 K7 T3 [8 g. W* T8 I else: - R# u9 G2 F0 [6 \# a# `! m if other.left is None or other.left.color==BLACK: & W% E+ r$ R) e* N" l6 [ if other.right is not None:9 A) Z/ ^* W: R+ k. i
other.right.color=BLACK 7 D# {; }8 _; _+ P8 D/ i' E6 {/ Q0 x9 V0 d- H
other.color=RED ) @$ u& I k, p3 y0 m self.rb_rotate_left(other) g% A1 G( A; r- F4 o
other=parent.left& L, @9 J( y5 h' j; f2 c
; u1 T3 L: p& f @' K8 C! c
other.color=parent.color 6 \1 \$ I- P2 h7 y5 J parent.color=BLACK ) u* L. j6 t2 T5 r+ k6 Z* ]8 I& [' ^0 L' Z+ b, F$ X
if other.left is not None: % L: K' Y7 D" S( L7 X q w other.left.color=BLACK' r. p' P. k/ E) X$ i8 O
* h4 m1 Z; b+ U0 x# a, x4 S Q self.rb_rotate_right(parent) $ j, w' P1 b1 ]/ R9 L7 t node=self.root # g3 _: n) {9 R6 v0 X+ V* Y: U" d break% F/ |. c w$ X+ U) ?
3 r- N" R3 g& |: `3 L# S& l$ Q6 V6 ^" `% B; S9 s
5 a1 O3 i! ^$ N! j4 Z! ]8 d if node is not None:" z# T) q( ^2 e+ Q5 w( f- z% x
node.color=BLACK * o0 a R6 Y4 q1 L9 q & k( q. }, s3 t2 g5 e+ } def rb_erase(self,data): ' ^% `! {* `) J4 v tmp_node=Node(data) ) @6 k5 H5 J( u6 D) W- |# H node,parent = self.rb_search_auxiliary(tmp_node)2 R: ^# c. i" k! k
if node is None: 5 s- U O, X' E7 { print "data is not exist." 1 }/ k' R* U5 P$ O6 I, H return! {9 X( @6 q( Z2 V0 M
2 X5 B. v7 s! `6 \* }2 s0 b- z$ _
old =node# _7 | c- T# \1 U6 {2 V( I
if node.left and node.right: + u* C9 L; z: a' v: _) A/ W node=node.right1 H$ ]3 P4 |7 v) f }# Y, ?
& I+ x5 v1 B1 S, ?0 J! m# f left=node.left 7 v* B2 l% N7 I while left is not None:1 w; ~8 c1 B. T
node =left' R* o) F. Y9 s) R' t: T
left=node.left 4 P1 _) E5 P0 B6 ~# Y$ ?; O / m9 A- T5 E: Q0 I% u" d6 y child=node.right ; d) S: Q5 b I) X: `1 F0 ]" P parent=node.parent6 ~6 C, [' f b( S! H6 e, B
color=node.color" {) ~# ^! x( o4 ]7 x* Z
$ L% w0 g' h, I5 p7 p& l( ` if child: ) Z) Y7 l7 |5 e5 c( F% i1 d% m child.parent=parent 1 C& i3 L# F. u) a4 ~ if parent:! V. z& V b) R5 d4 W- W
if parent.left==node:1 f: ^& y7 z/ F' \, O
parent.left=child 4 V* i. {# q: R6 B2 V- T( g& } else:2 x& E) u+ I1 j; i, A
parent.right=child 3 [( ^3 Y' i$ z! Y% W " [8 M. H3 c( `8 p5 v$ b else:( f: C- S- b: _
self.root=child$ k9 F: D$ b) I2 }* ^ I
( c; ?! z$ e2 d) {5 S! w
if node.parent==old:! h3 ], k$ c* J9 k( \& P
parent=node , ]2 u0 W8 g' e# s( ?/ Q node.parent=old.parent$ C1 h d, h* `0 v& t9 m& y
node.color=old.color7 Z! I5 q. c" n# h! ~' U7 [3 O
node.right=old.right) M& c" q1 n O# s! e* Q A
node.left=old.left9 b4 O: P5 T5 ~
& D! q R6 G3 B& @ if old.parent:; T6 I6 [+ d6 m1 m* x9 U7 u
if old.parent.left==old: ! b+ ~7 u) I& o' H/ c2 j2 _ old.parent.left=node7 F! ]4 l4 P C' K; d9 l" z
else:1 x: T# B9 J& ^: n
old.parent.right=node ! G; l7 U$ J1 x- G; z/ q& m else: ( @' D9 _& n& ?# T/ J self.root=node * |; g7 e- h* O5 a1 N# ~- b: T6 Q2 D3 Y- T$ m
old.left.parent=node ) `5 @6 T! ]9 r& _+ n# L- M if old.right: ( i$ |' o" ?( ~4 _4 W" ]7 {2 M' b old.right.parent=node2 a$ y! p2 H+ K
" a* R. X) _: S) h. Y- V) j
else:& L* e, v- d& F. W' h4 e/ x5 o6 Z
if node.left is None:+ w" \/ K+ a" n6 c
child =node.right/ p: c1 }/ K% q( O2 e) F
else: ! m4 G2 \' G; O0 A. z" ~7 i/ ?; z3 m if node.left is not None: 0 `- K/ T: ?- F child=node.left4 r) m1 _, V7 A/ d
else: + n1 |9 A+ S- e' x child=None . A4 h, f) H8 ~3 G parent=node.parent , C+ G$ i$ N% O. M9 y( k$ y1 M5 \. R color=node.color + R v: {" u& S3 z if child:# E# ~4 D/ O+ A# S
child.parent=parent: Z- [1 |( B" U
if parent:. K2 t) x1 E9 n+ x# k
if parent.left==node: 8 {6 ], {( b1 Y Y9 I0 w$ _$ D3 R5 j parent.left=child7 w* m! j: z. \( s
else: 8 |! z7 j! `$ ]7 f0 K! L0 H, I: u parent.right=child + {; [/ m+ a/ B2 | else: ) T( v5 c3 @" v0 k; G- H* a& R4 _ self.root=child. P r% U4 T% w5 R) ?( Q# `. Q
- _7 u7 }0 s6 `
if color==BLACK: / @; d: `* f# C% Y5 u , t, d! O% U+ _( z; {$ U( F self.rb_erase_rebalance(child,parent); q5 a5 ?' e' {
1 z- r6 Z7 `6 f9 x0 u- v
8 c: ^6 R# d3 A- A
def rb_travelse(self,node): + i! t) C p8 c if node is not None:5 s( C' |0 [9 T* E
print str(node.data)+'\t'+str(node.color)( C: S \" Z- t1 t3 j1 [0 G" @
self.rb_travelse(node.left) P0 n! e2 X! o# X; ~% k' m if node.parent:$ z* |# U7 n% r
if node.parent.color==0 and node.color==0: 4 A) _+ U. C) g. i: Q print "error"$ }5 L- C5 c( U" ?2 I0 A" B
return ! v2 L0 w( F: i+ | self.rb_travelse(node.right)) l4 d7 P. n! P' Y1 u
if node.parent: , s" V% I3 q4 ~5 q0 ^6 F if node.parent.color==0 and node.color==0: 7 N" `+ M7 Q" l, b# W s print "error" v2 {/ ^5 U) B5 N4 ^ return 3 H3 X, Z2 r o3 E$ E) a" {& u. x2 S8 e, c7 f
return 7 o6 K/ Y, v$ [" S ( m3 \# n2 n2 _. i1 `9 {' M # M: p' g4 m% c) ]1 B; P
def cmp(self,node1,node2): ! R9 J7 C: i+ m if node1.data>node2.data : $ k2 L y# l7 a return 1 * F) o1 l4 p, n# i8 ` if node1.data==node2.data : 9 I @' o1 q: O8 W8 B return 0, F: \( k% Q0 c- y) h
if node1.data<node2.data: 7 O. R) ]7 M1 {4 k/ J- t return -1 / [) ~# u- j2 P! u6 L ' {- _# l6 m# J2 H4 l) aif __name__=="__main__": , B# w! r. t0 c+ D3 V2 D print "main" 6 B- n* m- t; z8 _9 ^ X! ~ data=[28,6,39,78,6,43,61,56,71,38]. }# z0 c' b2 O8 o( N s
#for i in range(10):3 Q: R* T) E- k Q* d! y
# rand_num = random.randint(0, 100)" U7 z" v8 B% k
# data.append(rand_num) . U% o3 O, h; j$ u. L! w #print data - ]/ _4 p- F) o* F, o t=RBtree()+ C: W; r S% g1 R
+ z# W3 }5 n/ N
5 Z7 ~1 s9 {# p' } for i in range(10):/ N( {& F) u, o; [( P/ ^ H
t.rb_insert(data[i])2 ]0 Q( f) J7 v# i3 A% i$ F6 _
0 [* i' b+ j! I7 z- } ! V) @$ P0 t0 ?/ U. f& v t.rb_travelse(t.root)$ z4 m# A1 k: i) m2 W1 m0 Z9 O, A5 p
( S+ f! C. C1 B% s$ }& e6 T; U
print "---------------------------------"8 C1 }; Z! s4 o B
t.rb_erase(data[7])& I+ z4 V! S, C& y5 G5 z3 v) g
+ `0 c! T$ J2 T7 s7 v t.rb_travelse(t.root) . d6 H3 s( \$ {; T. ]$ j2 K+ l. z# H& C