#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "diskBTree.h"
static void restoreBTree(DiskBTree *tree, BTNode *node);
static int searchNodePos(BTNode *node, KeyType key) {
int i = 1;
while (i <= node->keyNum && key > node->key[i]) {
i++;
}
return i;
}
static void split(BTNode **node, int s, BTNode **other) {
int i = s + 1;
int j = 1;
int n = (*node)->keyNum;
BTNode *splitNode = (BTNode *) malloc(sizeof(BTNode));
memset(splitNode, 0, sizeof(BTNode));
*other = splitNode;
splitNode->ptr[0] = (*node)->ptr[s];
for (; i <= n; ++i, ++j) {
splitNode->key[j] = (*node)->key[i];
splitNode->ptr[j] = (*node)->ptr[i];
(*node)->key[i] = 0;
(*node)->ptr[i] = 0;
}
splitNode->keyNum = MaxOrder - s;
splitNode->parent = (*node)->parent;
for (i = 0; i <= n - s; ++i) {
if (splitNode->ptr[i]) {
splitNode->ptr[i]->parent = splitNode;
}
}
(*node)->keyNum = s - 1;
}
static BTNode *createRootNode(KeyType key, BTNode *p0, BTNode *p1) {
BTNode *node = (BTNode *) malloc(sizeof(BTNode));
memset(node, 0, sizeof(BTNode));
node->keyNum = 1;
node->key[1] = key;
node->ptr[0] = p0;
node->ptr[1] = p1;
if (p0) {
p0->parent = node;
}
if (p1) {
p1->parent = node;
}
node->parent = NULL;
return node;
}
static void insertNode(BTNode *node, int pos, KeyType key, BTNode *child) {
int i;
int n = node->keyNum;
for (i = n; i >= pos; --i) {
node->key[i + 1] = node->key[i];
node->ptr[i + 1] = node->ptr[i];
}
node->key[pos] = key;
node->ptr[pos] = child;
if (child) {
child->parent = node;
}
node->keyNum++;
}
static void insertBTree(DiskBTree *tree, KeyType key, BTNode *node, int pos) {
int finish = 0;
int needNewRoot = 0;
BTNode *child = NULL;
int mid;
KeyType x = key;
if (node) {
while (!finish && !needNewRoot) {
insertNode(node, pos, x, child);
if (node->keyNum < MaxOrder) {
finish = 1;
} else {
mid = (MaxOrder + 1) / 2;
split(&node, mid, &child);
x = node->key[mid];
if (node->parent) {
node = node->parent;
pos = searchNodePos(node, x);
} else {
needNewRoot = 1;
}
}
}
} else {
tree->root = createRootNode(key, NULL, NULL);
tree->count = 1;
}
if (needNewRoot) {
tree->root = createRootNode(x, node, child);
}
}
void insertKey(DiskBTree *tree, KeyType key) {
Result res;
searchBTree(tree, key, &res);
if (res.tag == 1) {
printf("键值 %d 已经存在了!\n", key);
} else {
insertBTree(tree, key, res.ptr, res.pos);
tree->count++;
}
}
static void borrowFromBrother(BTNode *node, BTNode *leftBrother, BTNode *rightBrother, BTNode *parent, int pos) {
if (leftBrother && leftBrother->keyNum >= ((MaxOrder + 1) / 2)) {
for (int j = node->keyNum + 1; j > 0; --j) {
if (j > 1) {
node->key[j] = node->key[j - 1];
}
node->ptr[j] = node->ptr[j - 1];
}
node->ptr[0] = leftBrother->ptr[leftBrother->keyNum];
if (node->ptr[0]) {
node->ptr[0]->parent = node;
}
leftBrother->ptr[leftBrother->keyNum] = NULL;
node->key[1] = parent->key[pos];
parent->key[pos] = leftBrother->key[leftBrother->keyNum];
leftBrother->keyNum--;
node->keyNum++;
} else if (rightBrother && rightBrother->keyNum >= ((MaxOrder + 1) / 2)) {
node->key[node->keyNum + 1] = parent->key[pos + 1];
node->ptr[node->keyNum + 1] = rightBrother->ptr[0];
if (node->ptr[node->keyNum + 1]) {
node->ptr[node->keyNum + 1]->parent = node;
}
node->keyNum++;
parent->key[pos + 1] = rightBrother->key[1];
for (int j = 0; j < rightBrother->keyNum; ++j) {
if (j > 0) {
rightBrother->key[j] = rightBrother->key[j + 1];
}
rightBrother->ptr[j] = rightBrother->ptr[j + 1];
}
rightBrother->ptr[rightBrother->keyNum] = NULL;
rightBrother->keyNum--;
}
}
static void mergerWithLeftBrother(BTNode *leftBrother, BTNode *parent, BTNode *node, DiskBTree *tree, int pos) {
leftBrother->key[leftBrother->keyNum + 1] = parent->key[pos];
leftBrother->ptr[leftBrother->keyNum + 1] = node->ptr[0];
if (leftBrother->ptr[leftBrother->keyNum + 1]) {
leftBrother->ptr[leftBrother->keyNum + 1]->parent = leftBrother;
}
leftBrother->keyNum++;
for (int i = 1; i <= node->keyNum; ++i) {
leftBrother->key[leftBrother->keyNum + i] = node->key[i];
leftBrother->ptr[leftBrother->keyNum + i] = node->ptr[i];
if (leftBrother->ptr[leftBrother->keyNum + i]) {
leftBrother->ptr[leftBrother->keyNum + i]->parent = leftBrother;
}
}
leftBrother->keyNum += node->keyNum;
parent->ptr[pos] = NULL;
free(node);
for (int j = pos; j < parent->keyNum; ++j) {
parent->key[j] = parent->key[j + 1];
parent->ptr[j] = parent->ptr[j + 1];
}
parent->ptr[parent->keyNum] = NULL;
parent->keyNum--;
if (tree->root == parent) {
if (parent->keyNum == 0) {
for (int i = 0; i <= parent->keyNum + 1; ++i) {
if (parent->ptr[i]) {
tree->root = parent->ptr[i];
break;
}
tree->root->parent = NULL;
}
}
} else {
if (parent->keyNum < ((MaxOrder - 1) / 2)) {
restoreBTree(tree, parent);
}
}
}
static void mergerWithRightBrother(BTNode *rightBrother, BTNode *parent, BTNode *node, DiskBTree *tree, int pos) {
for (int i = rightBrother->keyNum; i > 0; --i) {
if (i > 0) {
rightBrother->key[i + 1 + node->keyNum] = rightBrother->key[i];
}
rightBrother->ptr[i + 1 + node->keyNum] = rightBrother->ptr[i];
}
rightBrother->key[node->keyNum + 1] = parent->key[pos + 1];
for (int i = 0; i <= node->keyNum; ++i) {
if (i > 0) {
rightBrother->key[i] = node->key[i];
}
rightBrother->ptr[i] = node->ptr[i];
if (rightBrother->ptr[i]) {
rightBrother->ptr[i]->parent = rightBrother;
}
}
rightBrother->keyNum += (node->keyNum + 1);
parent->ptr[pos] = NULL;
free(node);
for (int i = pos; i < parent->keyNum; ++i) {
if (i > pos) {
parent->key[i] = parent->key[i + 1];
}
parent->ptr[i] = parent->ptr[i + 1];
}
if (parent->keyNum == 1) {
parent->ptr[0] = parent->ptr[1];
}
parent->ptr[parent->keyNum] = NULL;
parent->keyNum--;
if (tree->root == parent) {
if (parent->keyNum == 0) {
for (int i = 0; i <= parent->keyNum; ++i) {
if (parent->ptr[i]) {
tree->root = parent->ptr[i];
break;
}
}
tree->root->parent = NULL;
}
} else {
if (parent->keyNum < ((MaxOrder - 1) / 2)) {
restoreBTree(tree, parent);
}
}
}
static void restoreBTree(DiskBTree *tree, BTNode *node) {
BTNode *parent, *leftBrother, *rightBrother;
parent = node->parent;
if (parent) {
int i;
for (i = 0; i <= parent->keyNum; ++i) {
if (parent->ptr[i] == node) {
break;
}
}
if (i > 0) {
leftBrother = parent->ptr[i - 1];
} else {
leftBrother = NULL;
}
if (i < parent->keyNum) {
rightBrother = parent->ptr[i + 1];
} else {
rightBrother = NULL;
}
if ((leftBrother && leftBrother->keyNum >= (MaxOrder + 1) / 2) ||
(rightBrother && rightBrother->keyNum >= (MaxOrder + 1) / 2)) {
borrowFromBrother(node, leftBrother, rightBrother, parent, i);
} else {
if (leftBrother) {
mergerWithLeftBrother(leftBrother, parent, node, tree, i);
} else if (rightBrother) {
mergerWithRightBrother(rightBrother, parent, node, tree, i);
} else {
for (int j = 0; j < node->keyNum; ++j) {
if (node->ptr[j]) {
tree->root = node->ptr[j];
break;
}
}
tree->root->parent = NULL;
}
}
} else {
BTNode *a;
for (int j = 0; j <= node->keyNum; ++j) {
if (node->ptr[j]) {
a = node;
node = node->ptr[j];
a->ptr[j] = NULL;
free(a);
break;
}
}
tree->root = node;
tree->root->parent = NULL;
}
}
static void successor(BTNode **node, int pos) {
BTNode *leaf = *node;
if (leaf == NULL) {
return;
}
leaf = leaf->ptr[pos];
while (leaf->ptr[0]) {
leaf = leaf->ptr[0];
}
(*node)->key[pos] = leaf->key[1];
(*node) = leaf;
}
static void removeNode(BTNode *node, int pos) {
for (int i = pos; i < node->keyNum; ++i) {
node->key[i] = node->key[i + 1];
node->ptr[i] = node->ptr[i + 1];
}
node->keyNum--;
}
static void deleteBTree(DiskBTree *tree, BTNode *node, int pos) {
if (node->ptr[pos]) {
successor(&node, pos);
deleteBTree(tree, node, 1);
} else {
removeNode(node, pos);
if (node->keyNum < ((MaxOrder - 1) / 2)) {
restoreBTree(tree, node);
}
}
}
void deleteKey(DiskBTree *tree, KeyType key) {
Result res;
searchBTree(tree, key, &res);
if (res.tag) {
deleteBTree(tree, res.ptr, res.pos);
tree->count--;
} else {
printf("关键字key不在B树上!\n");
}
}
DiskBTree *initDiskBTree() {
DiskBTree *bTree = (DiskBTree *) malloc(sizeof(DiskBTree));
bTree->root = NULL;
bTree->count = 0;
return bTree;
}
static void destroyBTNode(DiskBTree *tree, BTNode *node) {
if (node) {
for (int i = 0; i <= node->keyNum; ++i) {
if (node->ptr[i]) {
destroyBTNode(tree, node->ptr[i]);
}
}
free(node);
}
}
void releaseDiskBTree(DiskBTree *tree) {
if (tree) {
destroyBTNode(tree, tree->root);
free(tree);
}
}
void searchBTree(DiskBTree *tree, KeyType key, Result *res) {
BTNode *cur = tree->root;
BTNode *pre = NULL;
int tag = 0;
int pos;
while (cur && !tag) {
pos = searchNodePos(cur, key);
if (pos <= cur->keyNum && cur->key[pos] == key) {
tag = 1;
} else {
pre = cur;
cur = pre->ptr[pos - 1];
}
}
if (tag) {
res->tag = 1;
res->ptr = cur;
res->pos = pos;
} else {
res->tag = 0;
res->ptr = pre;
res->pos = pos;
}
}
void PrintBTree(const BTNode *node, int tab) {
if (!node) {
return;
}
int i;
for (i = 0; i <= tab; ++i) {
printf(" ");
}
for (i = 1; i <= node->keyNum; i++) {
printf("%d", node->key[i]);
if (i != node->keyNum) {
printf(", ");
}
}
printf("\n");
for (i = 0; i <= node->keyNum; i++) {
PrintBTree(node->ptr[i], tab + 1);
}
}
static void inOrderBTNode(BTNode *node) {
if (node) {
for (int i = 0; i <= node->keyNum; ++i) {
if (i > 0) {
printf("%d ", node->key[i]);
}
if (node->ptr[i]) {
inOrderBTNode(node->ptr[i]);
}
}
}
}
void orderTravelBTree(DiskBTree *tree) {
if (tree) {
printf("BTree order: ");
inOrderBTNode(tree->root);
printf("\n");
}
}