forked from t3nsor/codebook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SBT.cpp
147 lines (132 loc) · 3.74 KB
/
SBT.cpp
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
146
147
// Size-Balanced Tree, taken from
// http://blog.tomtung.com/2007/06/size-balanced-tree-in-cpp
// TODO: How does this behave with duplicate keys?
struct SBTNode {
SBTNode *ch[2], *p;
long key;
unsigned long size;
SBTNode(long _key, unsigned long _size);
} NIL = SBTNode(0, 0);
// To make an empty tree: SBTree t = &NIL;
typedef SBTNode *SBTree;
SBTNode::SBTNode(long _key, unsigned long _size = 1) {
ch[0] = ch[1] = p = &NIL;
size = _size;
key = _key;
}
// Returns node if key is found, &NIL otherwise
SBTNode *SBT_Search(SBTree T, long key);
// Example invocation: SBT_Insert(t, new SBTNode(42));
void SBT_Insert(SBTree &T, SBTNode *x);
// Careful, if no matching key is found, this will still
// delete a node from the tree. The deleted node is not
// freed, and a pointer to it is returned.
SBTNode *SBT_Delete(SBTree &T, long key);
// Returns first node whose key is strictly less than key,
// or &NIL if no such node
SBTNode *SBT_Pred(SBTree T, long key);
// Returns first node whose key is strictly greater than
// key, or &NIL if no such node
SBTNode *SBT_Succ(SBTree T, long key);
// Returns node with ith smallest value (1 <= i <= T->size)
SBTNode *SBT_Select(SBTree T, unsigned long i);
// Returns k such that key is the kth smallest key in the
// tree (1 <= k <= T->size), or 0 if key not found.
unsigned long SBT_Rank(SBTree T, long key);
inline void SBT_Rotate(SBTree &x, bool flag) {
SBTNode *y = x->ch[!flag];
// assert(x!=&NIL&&y!=&NIL);
y->p = x->p;
x->p = y;
if (y->ch[flag] != &NIL)
y->ch[flag]->p = x;
x->ch[!flag] = y->ch[flag];
y->ch[flag] = x;
y->size = x->size;
x->size = x->ch[0]->size + x->ch[1]->size + 1;
x = y;
}
void SBT_Maintain(SBTree &T, bool flag) {
if (T->ch[flag]->ch[flag]->size > T->ch[!flag]->size)
SBT_Rotate(T, !flag);
else if (T->ch[flag]->ch[!flag]->size > T->ch[!flag]->size) {
SBT_Rotate(T->ch[flag], flag);
SBT_Rotate(T, !flag);
} else
return;
SBT_Maintain(T->ch[0], 0), SBT_Maintain(T->ch[1], 1);
SBT_Maintain(T, 0), SBT_Maintain(T, 1);
}
SBTNode *SBT_Search(SBTree T, long key) {
return T == &NIL || T->key == key
? T
: SBT_Search(T->ch[key > T->key], key);
}
void SBT_Insert(SBTree &T, SBTNode *x) {
if (T == &NIL)
T = x;
else {
T->size++;
x->p = T;
SBT_Insert(T->ch[x->key > T->key], x);
SBT_Maintain(T, x->key > T->key);
}
}
SBTNode *SBT_Delete(SBTree &T, long key) {
if (T == &NIL)
return &NIL;
T->size--;
if (T->key == key || T->ch[key > T->key] == &NIL) {
SBTNode *toDel;
if (T->ch[0] == &NIL || T->ch[1] == &NIL) {
toDel = T;
T = T->ch[T->ch[1] != &NIL];
if (T != &NIL)
T->p = toDel->p;
} else {
toDel = SBT_Delete(T->ch[1], key - 1);
T->key = toDel->key;
}
return toDel;
} else
return SBT_Delete(T->ch[key > T->key], key);
}
SBTNode *SBT_Pred(SBTree T, long key) {
if (T == &NIL)
return &NIL;
if (key <= T->key)
return SBT_Pred(T->ch[0], key);
else {
SBTNode *pred = SBT_Pred(T->ch[1], key);
return (pred != &NIL ? pred : T);
}
}
SBTNode *SBT_Succ(SBTree T, long key) {
if (T == &NIL)
return &NIL;
if (key >= T->key)
return SBT_Succ(T->ch[1], key);
else {
SBTNode *succ = SBT_Succ(T->ch[0], key);
return (succ != &NIL ? succ : T);
}
}
SBTNode *SBT_Select(SBTree T, unsigned long i) {
unsigned long r = T->ch[0]->size + 1;
if (i == r)
return T;
else
return SBT_Select(T->ch[i > r], i > r ? i - r : i);
}
unsigned long SBT_Rank(SBTree T, long key) {
if (T == &NIL)
return 0;
if (T->key == key)
return T->ch[0]->size + 1;
else if (key < T->key)
return SBT_Rank(T->ch[0], key);
else {
unsigned long r = SBT_Rank(T->ch[1], key);
return r == 0 ? 0 : r + T->ch[0]->size + 1;
}
}