-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrbtree.py
146 lines (131 loc) · 3.98 KB
/
rbtree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
BLACK=0
RED=1
def inorder_traversal(node):
if node is None:
return
if node.left:
yield from inorder_traversal(node.left)
yield (node.key, node.value)
if node.right:
yield from inorder_traversal(node.right)
class Node:
def __init__(self, color, key, value, parent, left, right):
self.color = color
self.key = key
self.value = value
self.parent = parent
self.left = left
self.right = right
def uncle(self):
g = self.grandparent()
if g:
if g.left and g.left == self.parent:
return g.right
else:
return g.left
return None
def grandparent(self):
p = self.parent
if p:
return p.parent
return None
class RBTree:
def __init__(self):
self.root = None
def search(self, k):
if self.root:
return self.search_r(self.root, k)
return None
def search_r(self, root, k):
if k < root.key and root.left:
return self.search_r(root.left, k)
elif k > root.key and root.right:
return self.search_r(root.right, k)
elif k == root.key:
return root.value
return None
def insert(self, k, v):
if self.root:
new_node = self.insert_r(self.root, k, v)
if new_node:
root = new_node
while root.parent:
root = root.parent
self.root = root
else:
self.root = Node(BLACK, k, v, None, None, None)
def insert_r(self, root, k, v):
if k == root.key:
root.value = v
return None
elif k < root.key:
if root.left:
return self.insert_r(root.left, k, v)
node = Node(RED, k, v, root, None, None)
root.left = node
self.insert_repair(node)
return node
else:
if root.right:
return self.insert_r(root.right, k, v)
node = Node(RED, k, v, root, None, None)
root.right = node
self.insert_repair(node)
return node
def insert_repair(self, node):
if not node.parent:
node.color = BLACK
elif node.parent.color == BLACK:
pass
elif node.uncle() and node.uncle().color == RED:
node.parent.color = BLACK
node.uncle().color = BLACK
node.grandparent().color = RED
self.insert_repair(node.grandparent())
else:
n = node
p = node.parent
g = node.grandparent()
if node == p.right and p == g.left:
self.rotate_left(p)
n = node.left
elif node == p.left and p == g.right:
self.rotate_right(p)
n = node.right
if n:
p = n.parent
g = n.grandparent()
if n == p.left:
self.rotate_right(g)
else:
self.rotate_left(g)
p.color = BLACK
g.color = RED
def rotate_left(self, node):
new_node = node.right
p = node.parent
node.right = new_node.left
new_node.left = node
node.parent = new_node
if node.right:
node.right.parent = node
if p:
if node == p.left:
p.left = new_node
elif node == p.right:
p.right = new_node
new_node.parent = p
def rotate_right(self, node):
new_node = node.left
p = node.parent
node.left = new_node.right
new_node.right = node
node.parent = new_node
if node.left:
node.left.parent = node
if p:
if node == p.left:
p.left = new_node
elif node == p.right:
p.right = new_node
new_node.parent = p