-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
treap.cpp
258 lines (253 loc) · 7.69 KB
/
treap.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/**
* @file
* @brief A balanced binary search tree (BST) on the basis of binary search tree
* and heap: the [Treap](https://en.wikipedia.org/wiki/Treap) algorithm
* implementation
*
* @details
* Implementation of the treap data structre
*
* Support operations including insert, erase, and query (the rank of specified
* element or the element ranked x) as the same as BST
*
* But these operations take O(log N) time, since treap keeps property of heap
* using rotate operation, and the desired depth of the tree is O(log N).
* There's very little chance that it will degenerate into a chain like BST
*
* @author [Kairao ZHENG](https://github.com/fgmn)
*/
#include <array> /// For array
#include <cassert> /// For assert
#include <cstdint>
#include <iostream> /// For IO operations
/**
* @namespace
* @brief Data Structures
*/
namespace data_structures {
/**
* @namespace
* @brief Functions for the [Treap](https://en.wikipedia.org/wiki/Treap)
* algorithm implementation
*/
namespace treap {
const int maxNode = 1e5 + 5; ///< maximum number of nodes
/**
* @brief Struct representation of the treap
*/
struct Treap {
int root = 0; ///< root of the treap
int treapCnt = 0; ///< Total number of current nodes in the treap
std::array<int, maxNode> key = {}; ///< Node identifier
std::array<int, maxNode> priority = {}; ///< Random priority
std::array<std::array<int, 2>, maxNode> childs = {
{}}; ///< [i][0] represents the
///< left child of node i, and
///[i][1] represents the right
std::array<int, maxNode> cnt =
{}; ///< Maintains the subtree size for ranking query
std::array<int, maxNode> size = {}; ///< The number of copies per node
/**
* @brief Initialization
*/
Treap() : treapCnt(1) {
priority[0] = INT32_MAX;
size[0] = 0;
}
/**
* @brief Update the subtree size of the node
* @param x The node to update
*/
void update(int x) {
size[x] = size[childs[x][0]] + cnt[x] + size[childs[x][1]];
}
/**
* @brief Rotate without breaking the property of BST
* @param x The node to rotate
* @param t 0 represent left hand, while 1 right hand
*/
void rotate(int &x, int t) {
int y = childs[x][t];
childs[x][t] = childs[y][1 - t];
childs[y][1 - t] = x;
// The rotation will only change itself and its son nodes
update(x);
update(y);
x = y;
}
/**
* @brief Insert a value into the specified subtree (internal method)
* @param x Insert into the subtree of node x (Usually x=root)
* @param k Key to insert
*/
void _insert(int &x, int k) {
if (x) {
if (key[x] == k) {
cnt[x]++;
} // If the node already exists, the number of copies is ++
else {
int t = (key[x] < k); // Insert according to BST properties
_insert(childs[x][t], k);
// After insertion, the heap properties are retained by rotation
if (priority[childs[x][t]] < priority[x]) {
rotate(x, t);
}
}
} else { // Create a new node
x = treapCnt++;
key[x] = k;
cnt[x] = 1;
priority[x] = rand(); // Random priority
childs[x][0] = childs[x][1] = 0;
}
update(x);
}
/**
* @brief Erase a value from the specified subtree (internal method)
* @param x Erase from the subtree of node x (Usually x=root)
* @param k Key to erase
*/
void _erase(int &x, int k) {
if (key[x] == k) {
if (cnt[x] > 1) {
cnt[x]--;
} // If the node has more than one copy, the number of copies --
else {
if (childs[x][0] == 0 && childs[x][1] == 0) {
x = 0;
return;
} // If there are no children, delete and return
// Otherwise, we need to rotate the sons and delete them
// recursively
int t = (priority[childs[x][0]] > priority[childs[x][1]]);
rotate(x, t);
_erase(x, k);
}
} else { // Find the target value based on BST properties
_erase(childs[x][key[x] < k], k);
}
update(x);
}
/**
* @brief Find the KTH largest value (internal method)
* @param x Query the subtree of node x (Usually x=root)
* @param k The queried rank
* @return The element ranked number k
*/
int _get_k_th(int &x, int k) {
if (k <= size[childs[x][0]]) {
return _get_k_th(childs[x][0], k);
}
k -= size[childs[x][0]] + cnt[x];
if (k <= 0) {
return key[x];
}
return _get_k_th(childs[x][1], k);
}
/**
* @brief Query the rank of specified element (internal method)
* @param x Query the subtree of node x (Usually x=root)
* @param k The queried element
* @return The rank of element k
*/
int _get_rank(int x, int k) {
if (!x) {
return 0;
}
if (k == key[x]) {
return size[childs[x][0]] + 1;
} else if (k < key[x]) {
return _get_rank(childs[x][0], k);
} else {
return size[childs[x][0]] + cnt[x] + _get_rank(childs[x][1], k);
}
}
/**
* @brief Get the predecessor node of element k
* @param k The queried element
* @return The predecessor
*/
int get_predecessor(int k) {
int x = root, pre = -1;
while (x) {
if (key[x] < k) {
pre = key[x], x = childs[x][1];
} else {
x = childs[x][0];
}
}
return pre;
}
/**
* @brief Get the successor node of element k
* @param k The queried element
* @return The successor
*/
int get_next(int k) {
int x = root, next = -1;
while (x) {
if (key[x] > k) {
next = key[x], x = childs[x][0];
} else {
x = childs[x][1];
}
}
return next;
}
/**
* @brief Insert element (External method)
* @param k Key to insert
*/
void insert(int k) { _insert(root, k); }
/**
* @brief Erase element (External method)
* @param k Key to erase
*/
void erase(int k) { _erase(root, k); }
/**
* @brief Get the KTH largest value (External method)
* @param k The queried rank
* @return The element ranked number x
*/
int get_k_th(int k) { return _get_k_th(root, k); }
/**
* @brief Get the rank of specified element (External method)
* @param k The queried element
* @return The rank of element k
*/
int get_rank(int k) { return _get_rank(root, k); }
};
} // namespace treap
} // namespace data_structures
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
data_structures::treap::Treap mTreap; ///< Treap object instance
mTreap.insert(1);
mTreap.insert(2);
mTreap.insert(3);
assert(mTreap.get_k_th(2) == 2);
mTreap.insert(4);
mTreap.insert(5);
mTreap.insert(6);
assert(mTreap.get_next(4) == 5);
mTreap.insert(7);
assert(mTreap.get_predecessor(7) == 6);
mTreap.erase(4);
assert(mTreap.get_k_th(4) == 5);
assert(mTreap.get_rank(5) == 4);
mTreap.insert(10);
assert(mTreap.get_rank(10) == 7);
assert(mTreap.get_predecessor(10) == 7);
std::cout << "All tests have successfully passed!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}