Skip to content

Commit a794d8e

Browse files
author
fuli
committed
refactor btree impl.
1 parent 9c0d63d commit a794d8e

File tree

2 files changed

+143
-136
lines changed

2 files changed

+143
-136
lines changed

include/btree.h

Lines changed: 139 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ namespace alg {
7373
fd = open(path, O_RDWR|O_CREAT, 0640);
7474
if (fd == -1)
7575
return;
76-
node x = (node)allocate_node();
76+
node x = (node)ALLOCBLK();
7777
int n = read(fd,x,BLOCKSIZE);
7878
if (n != BLOCKSIZE) { // init new btree
7979
x->flag |= LEAF;
@@ -97,7 +97,7 @@ namespace alg {
9797
r->flag &= ~ONDISK;
9898
WRITE(r);
9999
// new root
100-
node s = (node)allocate_node();
100+
node s = (node)ALLOCBLK();
101101
s->flag &= ~LEAF;
102102
s->flag |= ONDISK; // write to offset 0
103103
s->offset = 0;
@@ -143,9 +143,9 @@ namespace alg {
143143
*/
144144
void insert_nonfull(node x, int32_t k) {
145145
int32_t i = x->n-1;
146-
if (x->flag & LEAF) { // insert into leaf
147-
while (i>=0 && k < x->key[i]) { // shift from right to left, when k < key[i]
148-
x->key[i+1] = x->key[i];
146+
if (x->flag & LEAF) { // insert into this leaf
147+
while (i>=0 && k < x->key[i]) { // right shift to
148+
x->key[i+1] = x->key[i]; // make place for k
149149
i = i - 1;
150150
}
151151
x->key[i+1] = k;
@@ -156,38 +156,26 @@ namespace alg {
156156
i = i-1;
157157
}
158158
i=i+1;
159-
node xi = READ(x, i);
159+
node xi = READ(x, i); // insert the key into one child.
160160
if (xi->n == 2*T-1) {
161161
split_child(x, i);
162162
if (k > x->key[i]) {
163163
i = i+1;
164164
}
165-
// reload x[i] after split_child(will modify child x[i])
165+
// NOTICE!
166+
// reload x[i] after split_child.
166167
xi = READ(x, i);
167168
}
168169
insert_nonfull(xi, k);
169170
delete xi;
170171
}
171172
}
172173

173-
/**
174-
* allocate empty node struct
175-
*/
176-
void * allocate_node() {
177-
node x = new node_t;
178-
x->n = 0;
179-
x->offset = 0;
180-
x->flag = 0;
181-
memset(x->key, 0, sizeof(x->key));
182-
memset(x->c, 0, sizeof(x->c));
183-
return x;
184-
}
185-
186174
/**
187175
* split a node into 2.
188176
*/
189177
void split_child(node x, int32_t i) {
190-
std::auto_ptr<node_t> z((node)allocate_node());
178+
std::auto_ptr<node_t> z((node)ALLOCBLK());
191179
std::auto_ptr<node_t> y(READ(x, i));
192180
z->flag &= ~LEAF;
193181
z->flag |= (y->flag & LEAF);
@@ -258,11 +246,13 @@ namespace alg {
258246
}
259247
}
260248

249+
/**
250+
* case 1.
251+
* If the key k is in node x and x is a leaf, delete the key k from x.
252+
*/
261253
void case1(node x, int32_t i, int32_t k) {
262-
// case 1.
263-
// If the key k is in node x and x is a leaf, delete the key k from x.
264254
int j;
265-
for (j = i;j<x->n-1;j++) { // shifting the keys.
255+
for (j = i;j<x->n-1;j++) { // shifting the keys only, no childs available.
266256
x->key[j] = x->key[j+1];
267257
}
268258
x->n = x->n - 1;
@@ -346,138 +336,139 @@ namespace alg {
346336

347337
void case3(node x, int32_t i, int32_t k) {
348338
std::auto_ptr<node_t> ci(READ(x, i));
339+
if (ci->n > T-1) { // ready to delete in child.
340+
delete_op(ci.get(), k);
341+
return;
342+
}
343+
349344
// case 3a.
350345
// If x.c[i] has only t - 1 keys but has an immediate sibling with at least t keys,
351346
// give x.c[i] an extra key by moving a key from x down into x.c[i], moving a
352347
// key from x.c[i]’s immediate left or right sibling up into x, and moving the
353348
// appropriate child pointer from the sibling into x.c[i].
354-
if (ci->n == T-1) {
355-
std::auto_ptr<node_t> left(READ(x, i-1));
356-
if (i-1>=0 && left->n >= T) {
357-
// printf("case3a, left");
358-
// right shift keys and childs of x.c[i] to make place for a key
359-
// right shift ci childs
349+
std::auto_ptr<node_t> left(READ(x, i-1));
350+
if (i-1>=0 && left->n >= T) {
351+
// printf("case3a, left");
352+
// right shift keys and childs of x.c[i] to make place for a key
353+
// right shift ci childs
354+
int j;
355+
for (j=ci->n-1;j>0;j--) {
356+
ci->key[j] = ci->key[j-1];
357+
}
358+
359+
for (j=ci->n;j>0;j--) {
360+
ci->c[j] = ci->c[j-1];
361+
}
362+
ci->n = ci->n+1;
363+
ci->key[0] = x->key[i-1]; // copy key from x[i-1] to ci[0]
364+
ci->c[0] = left->c[left->n]; // copy child from left last child.
365+
x->key[i] = left->key[left->n-1]; // copy left last key into x[i]
366+
left->n = left->n-1; // decrease left size
367+
368+
WRITE(ci.get());
369+
WRITE(x);
370+
WRITE(left.get());
371+
delete_op(ci.get(), k);
372+
return;
373+
}
374+
375+
// case 3a. right sibling
376+
std::auto_ptr<node_t> right(READ(x, i+1));
377+
if (i+1<=x->n && right->n >= T) {
378+
// printf("case3a, right");
379+
ci->key[ci->n] = x->key[i]; // append key from x
380+
ci->c[ci->n+1] = right->c[0]; // append child from right
381+
ci->n = ci->n+1;
382+
x->key[i] = right->key[0]; // subsitute key in x
383+
384+
int j;
385+
for (j=0;j<right->n-1;j++) { // remove key[0] from right sibling
386+
right->key[j] = right->key[j+1];
387+
}
388+
389+
for (j=0;j<right->n;j++) { // and also the child c[0] of the right sibling.
390+
right->c[j] = right->c[j+1];
391+
}
392+
right->n = right->n - 1; // reduce the size of the right sibling.
393+
394+
WRITE(ci.get());
395+
WRITE(x);
396+
WRITE(right.get());
397+
delete_op(ci.get(), k); // recursive delete key in x.c[i]
398+
return;
399+
}
400+
401+
// case 3b.
402+
// If x.c[i] and both of x.c[i]’s immediate siblings have t-1 keys, merge x.c[i]
403+
// with one sibling, which involves moving a key from x down into the new
404+
// merged node to become the median key for that node.
405+
if ((i-1<0 ||left->n == T-1) && (i+1 <=x->n || right->n == T-1)) {
406+
if (left->n == T-1) {
407+
// copy x[i] to left
408+
left->key[left->n] = x->key[i];
409+
left->n = left->n + 1;
410+
411+
// remove key[i] from x and also the child
412+
// shrink the size & set the child-0 to left
413+
delete_i(x, i);
414+
360415
int j;
361-
for (j=ci->n-1;j>0;j--) {
362-
ci->key[j] = ci->key[j-1];
416+
// append x.c[i] into left sibling
417+
for (j=0;j<ci->n;j++) {
418+
left->key[left->n + j] = ci->key[j];
363419
}
364420

365-
for (j=ci->n;j>0;j--) {
366-
ci->c[j] = ci->c[j-1];
421+
for (j=0;j<ci->n+1;j++) {
422+
left->c[left->n + j] = ci->c[j];
367423
}
368-
ci->n = ci->n+1;
369-
ci->key[0] = x->key[i-1]; // copy key from x[i-1] to ci[0]
370-
ci->c[0] = left->c[left->n]; // copy child from left last child.
371-
x->key[i] = left->key[left->n-1]; // copy left last key into x[i]
372-
left->n = left->n-1; // decrease left size
373-
424+
left->n += ci->n; // left became 2T-1
425+
ci->flag |= MARKFREE; // free ci
426+
ci->n = 0;
374427
WRITE(ci.get());
375428
WRITE(x);
429+
// root check
430+
if (x->n == 0 && x->offset ==0) {
431+
left->flag |= MARKFREE;
432+
WRITE(left.get());
433+
left->flag &= ~MARKFREE;
434+
left->offset = 0;
435+
}
376436
WRITE(left.get());
377-
delete_op(ci.get(), k);
437+
delete_op(left.get(), k);
378438
return;
379-
}
380-
381-
// case 3a. right sibling
382-
std::auto_ptr<node_t> right(READ(x, i+1));
383-
if (i+1<=x->n && right->n >= T) {
384-
// printf("case3a, right");
385-
ci->key[ci->n] = x->key[i]; // append key from x
386-
ci->c[ci->n+1] = right->c[0]; // append child from right
387-
ci->n = ci->n+1;
388-
x->key[i] = right->key[0]; // subsitute key in x
439+
} else if (right->n == T-1) {
440+
// copy x[i] to x.c[i]
441+
ci->key[ci->n] = x->key[i];
442+
ci->n = ci->n + 1;
443+
// remove key[i] from x and also the child
444+
// shrink the size & set the child-0 to ci
445+
delete_i(x, i);
389446

390447
int j;
391-
for (j=0;j<right->n-1;j++) { // remove key[0] from right sibling
392-
right->key[j] = right->key[j+1];
448+
// append right sibling into x.c[i]
449+
for (j=0;j<right->n;j++) {
450+
ci->key[ci->n + j] = right->key[j];
393451
}
394452

395-
for (j=0;j<right->n;j++) { // and also the child c[0] of the right sibling.
396-
right->c[j] = right->c[j+1];
453+
for (j=0;j<right->n+1;j++) {
454+
ci->c[ci->n + j] = right->c[j];
397455
}
398-
right->n = right->n - 1; // reduce the size of the right sibling.
399-
400-
WRITE(ci.get());
401-
WRITE(x);
456+
ci->n += right->n; // ci became 2T-1
457+
right->flag |= MARKFREE; // free right
458+
right->n = 0;
402459
WRITE(right.get());
403-
delete_op(ci.get(), k); // recursive delete key in x.c[i]
404-
return;
405-
}
406-
407-
// case 3b.
408-
// If x.c[i] and both of x.c[i]’s immediate siblings have t-1 keys, merge x.c[i]
409-
// with one sibling, which involves moving a key from x down into the new
410-
// merged node to become the median key for that node.
411-
if ((i-1<0 ||left->n == T-1) && (i+1 <=x->n || right->n == T-1)) {
412-
if (left->n == T-1) {
413-
// copy x[i] to left
414-
left->key[left->n] = x->key[i];
415-
left->n = left->n + 1;
416-
417-
// remove key[i] from x and also the child
418-
// shrink the size & set the child-0 to left
419-
delete_i(x, i);
420-
421-
int j;
422-
// append x.c[i] into left sibling
423-
for (j=0;j<ci->n;j++) {
424-
left->key[left->n + j] = ci->key[j];
425-
}
426-
427-
for (j=0;j<ci->n+1;j++) {
428-
left->c[left->n + j] = ci->c[j];
429-
}
430-
left->n += ci->n; // left became 2T-1
431-
ci->flag |= MARKFREE; // free ci
432-
ci->n = 0;
433-
WRITE(ci.get());
434-
WRITE(x);
435-
// root check
436-
if (x->n == 0 && x->offset ==0) {
437-
left->flag |= MARKFREE;
438-
WRITE(left.get());
439-
left->flag &= ~MARKFREE;
440-
left->offset = 0;
441-
}
442-
WRITE(left.get());
443-
delete_op(left.get(), k);
444-
return;
445-
} else if (right->n == T-1) {
446-
// copy x[i] to x.c[i]
447-
ci->key[ci->n] = x->key[i];
448-
ci->n = ci->n + 1;
449-
// remove key[i] from x and also the child
450-
// shrink the size & set the child-0 to ci
451-
delete_i(x, i);
452-
453-
int j;
454-
// append right sibling into x.c[i]
455-
for (j=0;j<right->n;j++) {
456-
ci->key[ci->n + j] = right->key[j];
457-
}
458-
459-
for (j=0;j<right->n+1;j++) {
460-
ci->c[ci->n + j] = right->c[j];
461-
}
462-
ci->n += right->n; // ci became 2T-1
463-
right->flag |= MARKFREE; // free right
464-
right->n = 0;
465-
WRITE(right.get());
466-
WRITE(x);
467-
// root check
468-
if (x->n == 0 && x->offset ==0) {
469-
ci->flag |= MARKFREE;
470-
WRITE(ci.get());
471-
ci->flag &= ~MARKFREE;
472-
ci->offset = 0;
473-
}
460+
WRITE(x);
461+
// root check
462+
if (x->n == 0 && x->offset ==0) {
463+
ci->flag |= MARKFREE;
474464
WRITE(ci.get());
475-
delete_op(ci.get(), k);
476-
return;
465+
ci->flag &= ~MARKFREE;
466+
ci->offset = 0;
477467
}
468+
WRITE(ci.get());
469+
delete_op(ci.get(), k);
470+
return;
478471
}
479-
} else {
480-
delete_op(ci.get(), k);
481472
}
482473
}
483474

@@ -496,11 +487,23 @@ namespace alg {
496487
x->n = x->n - 1;
497488
}
498489

490+
/**
491+
* allocate empty node struct
492+
*/
493+
void * ALLOCBLK() {
494+
node x = new node_t;
495+
x->n = 0;
496+
x->offset = 0;
497+
x->flag = 0;
498+
memset(x->key, 0, sizeof(x->key));
499+
memset(x->c, 0, sizeof(x->c));
500+
return x;
501+
}
499502
/**
500503
* Load the root block
501504
*/
502505
node ROOT() {
503-
void *root = allocate_node();
506+
void *root = ALLOCBLK();
504507
lseek(fd, 0, SEEK_SET);
505508
read(fd, root, BLOCKSIZE);
506509
return (node)root;
@@ -510,7 +513,7 @@ namespace alg {
510513
* Read a 4K-block from disk, and returns the node struct.
511514
*/
512515
node READ(node x, int32_t i) {
513-
void *xi = allocate_node();
516+
void *xi = ALLOCBLK();
514517
if (i >=0 && i <= x->n) {
515518
lseek(fd, x->c[i], SEEK_SET);
516519
read(fd, xi, BLOCKSIZE);

src/btree_demo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ int main(void) {
99
for (i=0;i<1000;i++) {
1010
x.Insert(i);
1111
printf("insert %d\n", i);
12+
BTree::Res r = x.Search(i);
13+
if (r.idx == -1) {
14+
printf("key[%d] insert failed\n", i);
15+
}
1216
}
1317

1418
for (i=0;i<1000;i++) {

0 commit comments

Comments
 (0)