说实话,需要考虑的情况很多,写的很烦,写了大半天,调试了半天。只是测试了主函数中那个简单数据,具体的介绍在B树简要介绍。
#include "stdio.h"
template <typename keyType = int>
struct node
{
bool leaf;
int keyNum;
keyType *keyList;
node **children;
node (int, bool);
};
template <typename keyType>
node<keyType> :: node (int leastChildNum, bool leaf)
{
this->keyNum = 0;
this->leaf = leaf;
this->keyList = new keyType[leastChildNum * 2 - 1];
this->children = new node*[leastChildNum * 2];
}
template <typename keyType = int>
struct btree
{
node<keyType> *root;
int leastChildNum;
void (*func) (keyType);
static void print (keyType);
btree (int, void (*) (keyType) = NULL);
void travese (node<keyType>*);
void insert (node<keyType>*, keyType);
void remove (node<keyType>*, keyType);
node<keyType>* split (node<keyType>*);
void merge (node<keyType>*, node<keyType>*, keyType);
};
template <typename keyType>
void btree<keyType> ::print (keyType key)
{
if (sizeof (keyType) == 1) {
printf("%c ", key);
return;
}
printf("%d ", key);
}
template <typename keyType>
btree<keyType> ::btree (int leastChildNum, void (*func) (keyType))
{
this->root = NULL;
this->leastChildNum = leastChildNum;
this->func = func == NULL ? print : func;
}
template <typename keyType>
void btree<keyType> ::travese (node<keyType> *root)
{
for (int e = 0; e < root->keyNum; e++) {
if (root->leaf == false) {
travese (root->children[e]);
}
func (root->keyList[e]);
}
if (root->leaf == false) {
travese (root->children[root->keyNum]);
}
}
template <typename keyType>
node<keyType>* btree<keyType> ::split (node<keyType> *left)
{
node<keyType> *right = new node<keyType> (leastChildNum, left->leaf);
right->keyNum = leastChildNum - 1;
for (int e = 0; e < right->keyNum; e++) {
right->keyList[e] = left->keyList[e + leastChildNum];
right->children[e] = left->children[e + leastChildNum];
}
right->children[right->keyNum] = left->children[leastChildNum * 2 - 1];
left->keyNum = leastChildNum - 1;
return right;
}
template <typename keyType>
void btree<keyType> ::insert (node<keyType> *root, keyType key)
{
// if the tree is NULL, or the node in root is full, the height of tree increase by 1.
if (root == NULL || (root == this->root && root->keyNum == leastChildNum * 2 - 1)) {
this->root = new node<keyType> (leastChildNum, root == NULL);
this->root->children[0] = root;
root = this->root;
}
int p = root->keyNum - 1;
// if current node is a leaf, insert the key.
if (root->leaf == true) {
while (p >= 0 && root->keyList[p] > key) {
root->keyList[p + 1] = root->keyList[p];
p--;
}
root->keyList[p + 1] = key;
root->keyNum++;
return;
}
// if current node is a interal node.
while (p >= 0 && root->keyList[p] > key) {
p--;
}
// if next child node will be searched is full, split it.
if (root->children[++p]->keyNum == leastChildNum * 2 - 1) {
keyType mid = root->children[p]->keyList[leastChildNum - 1];
node<keyType> *right = split (root->children[p]);
root->children[root->keyNum + 1] = root->children[root->keyNum];
for (int e = root->keyNum - 1; e >= p; e--) {
root->keyList[e + 1] = root->keyList[e];
root->children[e + 1] = root->children[e];
}
root->keyNum++;
root->keyList[p] = mid;
root->children[p + 1] = right;
}
// if the node is splited, and the key in the right subtree.
if (p < root->keyNum && root->keyList[p] < key) {
p++;
}
insert (root->children[p], key);
}
template <typename keyType>
void btree<keyType> ::merge (node<keyType> *left, node<keyType> *right, keyType mid)
{
left->keyList[leastChildNum - 1] = mid;
for (int e = 0; e < leastChildNum - 1; e++) {
left->keyList[e + leastChildNum] = right->keyList[e];
left->children[e + leastChildNum] = right->children[e];
}
left->children[leastChildNum * 2 - 1] = right->children[leastChildNum - 1];
left->keyNum = 2 * leastChildNum - 1;
}
template <typename keyType>
void btree<keyType> ::remove (node<keyType> *root, keyType key)
{
if (root == NULL) {
return;
}
int p = 0;
while (p < root->keyNum && key > root->keyList[p]) {
p++;
}
// if current node is a leaf node.
if (root->leaf == true) {
if (p == root->keyNum || key != root->keyList[p]) {
return;
}
while (p < root->keyNum - 1) {
root->keyList[p] = root->keyList[p + 1];
p++;
}
root->keyNum--;
return;
}
// if the key locate in current node.
if (p < root->keyNum && key == root->keyList[p]) {
if (root->children[p]->keyNum >= leastChildNum) {
root->keyList[p] = root->children[p]->keyList[root->children[p]->keyNum - 1];
remove (root->children[p], root->keyList[p]);
return;
}
if (root->children[p + 1]->keyNum >= leastChildNum) {
root->keyList[p] = root->children[p + 1]->keyList[0];
remove (root->children[p + 1], root->keyList[p]);
return;
}
merge (root->children[p], root->children[p + 1], key);
for (int e = p; e < root->keyNum - 1; e++) {
root->keyList[e] = root->keyList[e + 1];
root->children[e + 1] = root->children[e + 2];
}
//root->children[root->keyNum - 1] = root->children[root->keyNum];
root->keyNum--;
if (root->keyNum == 0 && root == this->root) {
this->root = root->children[p];
}
remove (root->children[p], key);
return;
}
// if the key do not locate in current node.
if (root->children[p]->keyNum >= leastChildNum) {
remove (root->children[p], key);
return;
}
node<keyType> *pthChild = root->children[p];
// if left sibling of the pth node has more than leastChildNum - 1 nodes,
// then borrow a node from it
if (p > 0 && root->children[p - 1]->keyNum >= leastChildNum) {
node<keyType> *leftSibling = root->children[p - 1];
pthChild->children[pthChild->keyNum + 1] = pthChild->children[pthChild->keyNum];
for (int e = pthChild->keyNum - 1; e >= 0; e--) {
pthChild->keyList[e + 1] = pthChild->keyList[e];
pthChild->children[e + 1] = pthChild->children[e];
}
pthChild->keyNum++;
pthChild->keyList[0] = root->keyList[p - 1];
pthChild->children[0] = leftSibling->children[leftSibling->keyNum];
root->keyList[p - 1] = leftSibling->keyList[leftSibling->keyNum - 1];
leftSibling->keyNum--;
remove (root->children[p], key);
return;
}
// if right sibling of pth node has more than leastChildNum - 1 nodes,
// then borrow a node from it
if (p < root->keyNum && root->children[p + 1]->keyNum >= leastChildNum) {
node<keyType> *rightSibling = root->children[p + 1];
pthChild->keyList[pthChild->keyNum] = root->keyList[p];
pthChild->children[pthChild->keyNum + 1] = rightSibling->children[0];
root->keyList[p] = rightSibling->keyList[0];
pthChild->keyNum++;
for (int e = 1; e < rightSibling->keyNum; e++) {
rightSibling->keyList[e - 1] = rightSibling->keyList[e];
rightSibling->children[e - 1] = rightSibling->children[e];
}
rightSibling->children[rightSibling->keyNum - 1] = rightSibling->children[rightSibling->keyNum];
rightSibling->keyNum--;
remove (root->children[p], key);
return;
}
// if both left and right siblings have only leastChildNum - 1 nodes,
// then merge one of sibling with current node
if (p > 0) {
p = p - 1;
}
merge (root->children[p], root->children[p + 1], root->keyList[p]);
for (int e = p; e < root->keyNum - 1; e++) {
root->keyList[e] = root->keyList[e + 1];
root->children[e + 1] = root->children[e + 2];
}
root->keyNum--;
if (root->keyNum == 0 && root == this->root) {
this->root = root->children[p];
}
remove (root->children[p], key);
return;
}
int main ()
{
char array[] = {
'G', 'M', 'P', 'W', 'A', 'C', 'D', 'E', 'J', 'K',
'N', 'O', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'F', 'L', 'Z' };
btree<char> tree (3);
for (int e = 0; e < 22; e++) {
tree.insert (tree.root, array[e]);
}
for (int e = 21; e >= 0; e--) {
tree.remove (tree.root, array[e]);
}
tree.travese (tree.root);
return 0;
}