@@ -42,14 +42,27 @@ T* DiskWrite(T* x) {
42
42
return x;
43
43
}
44
44
45
+ template <typename T>
46
+ T* AllocateNode (bool l) {
47
+ T* x = new T (l);
48
+ debug > 1 && std::cout << " alloc " << static_cast <void *>(x) << std::endl;
49
+ return x;
50
+ }
51
+
52
+ template <typename T>
53
+ void FreeNode (T* x) {
54
+ debug > 1 && std::cout << " free " << static_cast <void *>(x) << std::endl;
55
+ delete x;
56
+ }
57
+
45
58
template <typename T>
46
59
class BNode {
47
60
public:
48
61
BNode (bool l): n(0 ), key(0 ), c(0 ), leaf(l) {}
49
62
BNode<T>* recursive_destruct () {
50
63
if (!leaf)
51
64
for (auto i = c.begin (); i != c.end (); i++)
52
- delete ( *i)->recursive_destruct ();
65
+ FreeNode (( *i)->recursive_destruct () );
53
66
return this ;
54
67
}
55
68
size_t n;
@@ -59,10 +72,18 @@ class BNode {
59
72
};
60
73
61
74
template <typename T>
62
- BNode<T>* AllocateNode (bool l) {
63
- BNode<T>* x = new BNode<T>(l);
64
- debug > 1 && std::cout << " alloc " << static_cast <void *>(x) << std::endl;
65
- return x;
75
+ void pop_front (std::vector<T>& x) {
76
+ for (size_t i = 0 ; i < x.size () - 1 ; i++)
77
+ x[i] = x[i + 1 ];
78
+ x.pop_back ();
79
+ }
80
+
81
+ template <typename T>
82
+ void push_front (std::vector<T>& x, const T& k) {
83
+ x.push_back (k);
84
+ for (size_t i = x.size (); i > 0 ; i--)
85
+ x[i] = x[i - 1 ];
86
+ x[0 ] = k;
66
87
}
67
88
68
89
template <typename T>
@@ -83,12 +104,12 @@ class BTree {
83
104
return BTreeSearch (root, k);
84
105
}
85
106
BNode<T>* BTreeCreate () {
86
- BNode<T>* x = AllocateNode<T >(true );
107
+ BNode<T>* x = AllocateNode<BNode<T> >(true );
87
108
return DiskWrite (x);
88
109
}
89
110
void BTreeSplitChild (BNode<T>* x, size_t i) {
90
111
BNode<T>* y = x->c [i];
91
- BNode<T>* z = AllocateNode<T >(y->leaf );
112
+ BNode<T>* z = AllocateNode<BNode<T> >(y->leaf );
92
113
z->n = t - 1 ;
93
114
for (auto j = y->key .begin () + t; j != y->key .end (); j++)
94
115
z->key .push_back (*j);
@@ -137,14 +158,173 @@ class BTree {
137
158
void BTreeInsert (const T& k) {
138
159
BNode<T>* r = root;
139
160
if (r->n == 2 * t - 1 ) {
140
- BNode<T>* s = AllocateNode<T >(false );
161
+ BNode<T>* s = AllocateNode<BNode<T> >(false );
141
162
root = s;
142
163
s->c .push_back (r);
143
164
BTreeSplitChild (s, 0 );
144
165
BTreeInsertNonfull (s, k);
145
166
} else
146
167
BTreeInsertNonfull (r, k);
147
168
}
169
+ void BTreeMergeChild (BNode<T>* x, size_t i) {
170
+ // merge x->key[i] and z = x->c[i + 1] to y = x->c[i]
171
+ // assume y and z are read, assume y.n == z.n == t - 1
172
+ BNode<T> *y = x->c [i], *z = x->c [i + 1 ];
173
+ y->key .push_back (x->key [i]);
174
+ for (auto j = z->key .begin (); j != z->key .end (); j++)
175
+ y->key .push_back (*j);
176
+ for (auto j = z->c .begin (); j != z->c .end (); j++)
177
+ y->c .push_back (*j);
178
+ y->n = 2 * t - 1 ;
179
+ DiskWrite (y);
180
+ FreeNode (z);
181
+ for (size_t j = i; j < x->n - 1 ; j++) {
182
+ x->key [j] = x->key [j + 1 ];
183
+ x->c [j + 1 ] = x->c [j + 2 ];
184
+ }
185
+ x->key .pop_back ();
186
+ x->c .pop_back ();
187
+ x->n --;
188
+ DiskWrite (x);
189
+ }
190
+ void BTreeRotateLeft (BNode<T>* x, size_t i) {
191
+ // z = x->c[i + 1] ===> x->key[i] ===> y = x->c[i]
192
+ // assume y and z are read
193
+ BNode<T> *y = x->c [i], *z = x->c [i + 1 ];
194
+ y->key .push_back (x->key [i]);
195
+ x->key [i] = z->key [0 ];
196
+ pop_front (z->key );
197
+ if (!y->leaf ) {
198
+ y->c .push_back (z->c [0 ]);
199
+ pop_front (z->c );
200
+ }
201
+ y->n ++;
202
+ z->n --;
203
+ DiskWrite (x);
204
+ DiskWrite (y);
205
+ DiskWrite (z);
206
+ }
207
+ void BTreeRotateRight (BNode<T>* x, size_t i) {
208
+ // y = x->c[i] ===> x->key[i] ===> z = x->c[i + 1]
209
+ // assume y and z are read
210
+ BNode<T> *y = x->c [i], *z = x->c [i + 1 ];
211
+ push_front (z->key , x->key [i]);
212
+ x->key [i] = y->key [y->n - 1 ];
213
+ y->key .pop_back ();
214
+ if (!y->leaf ) {
215
+ push_front (z->c , y->c [y->n ]);
216
+ y->c .pop_back ();
217
+ }
218
+ z->n ++;
219
+ y->n --;
220
+ DiskWrite (x);
221
+ DiskWrite (y);
222
+ DiskWrite (z);
223
+ }
224
+ T BTreeDeleteMin (BNode<T>* x) {
225
+ if (x->leaf ) { // case 1
226
+ T ans = x->key [0 ];
227
+ pop_front (x->key );
228
+ x->n --;
229
+ return ans;
230
+ } else { // case 3
231
+ size_t i = x->n ;
232
+ BNode<T>* c = DiskRead (x->c [i]);
233
+ if (c->n == t - 1 ) {
234
+ if (DiskRead (x->c [i - 1 ])->n >= t)
235
+ BTreeRotateRight (x, i - 1 );
236
+ else // case 3.b
237
+ BTreeMergeChild (x, --i);
238
+ }
239
+ return BTreeDeleteMin (x->c [i]);
240
+ }
241
+ }
242
+ T BTreeDeleteMax (BNode<T>* x) {
243
+ if (x->leaf ) { // case 1
244
+ T ans = x->key [x->n - 1 ];
245
+ x->key .pop_back ();
246
+ x->n --;
247
+ return ans;
248
+ } else { // case 3
249
+ size_t i = 0 ;
250
+ BNode<T>* c = DiskRead (x->c [i]);
251
+ if (c->n == t - 1 ) {
252
+ if (DiskRead (x->c [i + 1 ])->n >= t)
253
+ BTreeRotateLeft (x, i);
254
+ else // case 3.b
255
+ BTreeMergeChild (x, i);
256
+ }
257
+ return BTreeDeleteMax (x->c [i]);
258
+ }
259
+ }
260
+ bool BTreeDelete (BNode<T>* x, const T& k) {
261
+ if (x->leaf ) { // case 1
262
+ bool deleting = false ;
263
+ for (size_t i = 0 ; i < x->n ; i++) {
264
+ if (!deleting) {
265
+ if (x->key [i] == k)
266
+ deleting = true ;
267
+ }
268
+ if (deleting && i + 1 < x->n ) {
269
+ x->key [i] = x->key [i + 1 ];
270
+ }
271
+ }
272
+ if (deleting) {
273
+ x->key .pop_back ();
274
+ x->n --;
275
+ }
276
+ DiskWrite (x);
277
+ return deleting;
278
+ }
279
+ bool k_in_x;
280
+ size_t i;
281
+ for (i = 0 ; i < x->n ; i++) {
282
+ if (x->key [i] == k) {
283
+ k_in_x = true ; // x->key[i] = k
284
+ break ;
285
+ }
286
+ if (x->key [i] > k) {
287
+ k_in_x = false ; // k in x->c[i]
288
+ break ;
289
+ }
290
+ }
291
+ if (k_in_x) { // case 2
292
+ BNode<T> *y = DiskRead (x->c [i]), *z = DiskRead (x->c [i + 1 ]);
293
+ if (y->n >= t) { // case 2.a
294
+ x->key [i] = BTreeDeleteMax (y);
295
+ return true ;
296
+ } else if (z->n >= t) { // 2.b
297
+ x->key [i] = BTreeDeleteMin (z);
298
+ return true ;
299
+ } else { // 2.c
300
+ BTreeMergeChild (x, i);
301
+ return BTreeDelete (y, k);
302
+ }
303
+ } else { // case 3
304
+ BNode<T>* c = DiskRead (x->c [i]);
305
+ if (c->n == t - 1 ) {
306
+ if (i < x->n && DiskRead (x->c [i + 1 ])->n >= t)
307
+ BTreeRotateLeft (x, i);
308
+ else if (i > 0 && DiskRead (x->c [i - 1 ])->n >= t)
309
+ BTreeRotateRight (x, i - 1 );
310
+ else { // case 3.b
311
+ if (i)
312
+ i--;
313
+ BTreeMergeChild (x, i);
314
+ }
315
+ }
316
+ return BTreeDelete (x->c [i], k);
317
+ }
318
+ }
319
+ bool BTreeDelete (const T& k) {
320
+ bool ans = BTreeDelete (root, k);
321
+ while (!root->n ) {
322
+ BNode<T>* ori = root;
323
+ root = DiskRead (root->c [0 ]);
324
+ FreeNode (ori);
325
+ }
326
+ return ans;
327
+ }
148
328
void print_tree (BNode<T>* x, size_t depth) {
149
329
std::string indent (4 * depth, ' ' );
150
330
std::cout << indent << " ___" << std::endl;
@@ -168,13 +348,18 @@ class BTree {
168
348
169
349
#ifdef MAIN_BTree
170
350
int main (int argc, char *argv[]) {
171
- size_t t = get_argv (argc, argv, 1 , 2 );
351
+ size_t t = get_argv (argc, argv, 1 , 3 );
172
352
debug = get_argv (argc, argv, 2 , 1 );
173
353
BTree<int > BT (t);
174
354
std::cout << " s / S: search" << std::endl;
175
355
std::cout << " i / I: insert" << std::endl;
356
+ std::cout << " d / D: delete" << std::endl;
176
357
std::cout << " p / P: print tree" << std::endl;
177
358
std::cout << " q / Q: quit" << std::endl;
359
+ // Generate tree in Page 498, Figure 18.7 (a):
360
+ // i10 i11 i13 i14 i15 i1 i3 i7 i4 i5 i16 i18 i19 i24 i25 i26 i20 i21 i22
361
+ // In Figure 18.7: i2 i17 i12 i6
362
+ // In Figure 18.8: d6 d13 d7 d4 d2
178
363
while (true ) {
179
364
char c; int x; std::pair<BNode<int >*, size_t > search_ans;
180
365
std::cout << " >> " ;
@@ -197,6 +382,12 @@ int main(int argc, char *argv[]) {
197
382
std::cin >> x;
198
383
BT.BTreeInsert (x);
199
384
break ;
385
+ case ' d' :
386
+ case ' D' :
387
+ std::cout << " x = " ;
388
+ std::cin >> x;
389
+ std::cout << std::boolalpha << BT.BTreeDelete (x) << std::endl;
390
+ break ;
200
391
case ' p' :
201
392
case ' P' :
202
393
BT.print_tree ();
0 commit comments