Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit 2cc6dcf

Browse files
committed
BTree.cpp
1 parent 17a578f commit 2cc6dcf

File tree

2 files changed

+201
-9
lines changed

2 files changed

+201
-9
lines changed

BTree.cpp

Lines changed: 200 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,27 @@ T* DiskWrite(T* x) {
4242
return x;
4343
}
4444

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+
4558
template <typename T>
4659
class BNode {
4760
public:
4861
BNode(bool l): n(0), key(0), c(0), leaf(l) {}
4962
BNode<T>* recursive_destruct() {
5063
if (!leaf)
5164
for (auto i = c.begin(); i != c.end(); i++)
52-
delete (*i)->recursive_destruct();
65+
FreeNode((*i)->recursive_destruct());
5366
return this;
5467
}
5568
size_t n;
@@ -59,10 +72,18 @@ class BNode {
5972
};
6073

6174
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;
6687
}
6788

6889
template <typename T>
@@ -83,12 +104,12 @@ class BTree {
83104
return BTreeSearch(root, k);
84105
}
85106
BNode<T>* BTreeCreate() {
86-
BNode<T>* x = AllocateNode<T>(true);
107+
BNode<T>* x = AllocateNode<BNode<T>>(true);
87108
return DiskWrite(x);
88109
}
89110
void BTreeSplitChild(BNode<T>* x, size_t i) {
90111
BNode<T>* y = x->c[i];
91-
BNode<T>* z = AllocateNode<T>(y->leaf);
112+
BNode<T>* z = AllocateNode<BNode<T>>(y->leaf);
92113
z->n = t - 1;
93114
for (auto j = y->key.begin() + t; j != y->key.end(); j++)
94115
z->key.push_back(*j);
@@ -137,14 +158,173 @@ class BTree {
137158
void BTreeInsert(const T& k) {
138159
BNode<T>* r = root;
139160
if (r->n == 2 * t - 1) {
140-
BNode<T>* s = AllocateNode<T>(false);
161+
BNode<T>* s = AllocateNode<BNode<T>>(false);
141162
root = s;
142163
s->c.push_back(r);
143164
BTreeSplitChild(s, 0);
144165
BTreeInsertNonfull(s, k);
145166
} else
146167
BTreeInsertNonfull(r, k);
147168
}
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+
}
148328
void print_tree(BNode<T>* x, size_t depth) {
149329
std::string indent(4 * depth, ' ');
150330
std::cout << indent << "___" << std::endl;
@@ -168,13 +348,18 @@ class BTree {
168348

169349
#ifdef MAIN_BTree
170350
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);
172352
debug = get_argv(argc, argv, 2, 1);
173353
BTree<int> BT(t);
174354
std::cout << "s / S: search" << std::endl;
175355
std::cout << "i / I: insert" << std::endl;
356+
std::cout << "d / D: delete" << std::endl;
176357
std::cout << "p / P: print tree" << std::endl;
177358
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
178363
while (true) {
179364
char c; int x; std::pair<BNode<int>*, size_t> search_ans;
180365
std::cout << ">> ";
@@ -197,6 +382,12 @@ int main(int argc, char *argv[]) {
197382
std::cin >> x;
198383
BT.BTreeInsert(x);
199384
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;
200391
case 'p':
201392
case 'P':
202393
BT.print_tree();

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,4 @@
113113
| 18 | BTree.cpp | B Tree Split Child | 494 |
114114
| 18 | BTree.cpp | B Tree Insert | 495 |
115115
| 18 | BTree.cpp | B Tree Insert Nonfull | 495 |
116+
| 18 | BTree.cpp | B Tree Insert Delete | 502 |

0 commit comments

Comments
 (0)