-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary_tree.py
More file actions
120 lines (106 loc) · 3.34 KB
/
Copy pathbinary_tree.py
File metadata and controls
120 lines (106 loc) · 3.34 KB
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
class Binary_Node:
def __init__(A, x): # O(1)
A.item = x
A.left = None
A.right = None
A.parent = None
A.subtree_update()
def height(A):
if A: return A.height
else: return -1
def subtree_update(A): # O(1)
A.height = 1 + max(A.height(A.left), A.height(A.right))
def skew(A): # O(1)
return A.height(A.right) - A.height(A.left)
def subtree_iter(A): # O(n)
if A.left: yield from A.left.subtree_iter()
yield A
if A.right: yield from A.right.subtree_iter()
def subtree_first(A): # O(logn)
if A.left: return A.left.subtree_first()
else: return A
def subtree_last(A): # O(logn)
if A.right: return A.right.subtree_last()
else: return A
def successor(A): # O(logn)
if A.right: return A.right.subtree_first()
while A.parent and (A is A.parent.right):
A = A.parent
return A.parent
def predecessor(A): # O(logn)
if A.left: return A.left.subtree_last()
while A.parent and (A is A.parent.left):
A = A.parent
return A.parent
def subtree_insert_before(A, B): # O(logn)
if A.left:
A = A.left.subtree_last()
A.right, B.parent = B, A
else:
A.left, B.parent = B, A
A.maintain()
def subtree_insert_after(A, B): # O(logn)
if A.right:
A = A.right.subtree_first()
A.left, B.parent = B, A
else:
A.right, B.parent = B, A
A.maintain()
def subtree_delete(A): # O(logn)
if A.left or A.right:
if A.left: B = A.predecessor()
else: B = A.successor()
A.item, B.item = B.item, A.item
return B.subtree_delete()
if A.parent:
if A.parent.left is A: A.parent.left = None
else: A.parent.right = None
A.parent.maintain()
return A
def subtree_rotate_right(D): # O(1)
assert D.left
B, E = D.left, D.right
A, C = B.left, B.right
D, B = B, D
D.item, B.item = B.item, D.item
B.left, B.right = A, D
D.left, D.right = C, E
if A: A.parent = B
if E: E.parent = D
B.subtree_update()
D.subtree_update()
def subtree_rotate_left(B): # O(1)
assert B.right
A, D = B.left, B.right
C, E = D.left, D.right
B, D = D, B
B.item, D.item = D.item, B.item
D.left, D.right = B, E
B.left, B.right = A, C
if A: A.parent = B
if E: E.parent = D
B.subtree_update()
D.subtree_update()
def rebalance(A): # O(1)
if A.skew() == 2:
if A.right.skew() < 0:
A.right.subtree_rotate_right()
A.subtree_rotate_left()
elif A.skew() == -2:
if A.left.skew() > 0:
A.left.subtree_rotate_left()
A.subtree_rotate_right()
def maintain(A): # O(log n)
A.rebalance()
A.subtree_update()
if A.parent: A.parent.maintain()
class Binary_Tree:
def __init__(T, Node_Type = Binary_Node):
T.root = None
T.size = 0
T.Node_Type = Node_Type
def __len__(T): return T.size
def __iter__(T):
if T.root:
for A in T.root.subtree_iter():
yield A.item