只实现了插入、查找算法,未实现删除算法。
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#define BTreeKey char
#define T 2 //minmum degree
#define TRUE 1
#define FALSE 0
struct BTree
{
struct BTreeNode * root;
};
struct BTreeNode
{
int n; //节点内关键字个数
char bLeaf;
BTreeKey keys[2*T-1];
struct BTreeNode * subTree[2*T];//至多有2T个孩子
};
struct BTreeResult
{
char ok; //是否成功
struct BTreeNode * node;
int index;
};
void BTreeCreate(struct BTree * tree)
{
struct BTreeNode * root = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
memset(root, 0, sizeof(struct BTreeNode));
root->bLeaf = TRUE;
root->n = 0;
//DISKWRITE(root)
tree->root = root;
}
struct BTreeNode * BTreeRead(struct BTreeNode * node, int subTreeIndex)
{
return node->subTree[subTreeIndex];
}
struct BTreeResult BTreeSearch(struct BTreeNode * node, BTreeKey k)
{
int i = 0;
while(i<node->n && k>node->keys[i])
i++;
if(i<node->n && k == node->keys[i])
{
struct BTreeResult res={1, node, i}; //TODO:optimize
return res;
}
else if(node->bLeaf)
{
struct BTreeResult res={0, 0, 0};
return res;
}
else
{
struct BTreeNode * childNode = 0;
childNode = BTreeRead(node, i);
return BTreeSearch(childNode, k);
}
struct BTreeResult res={0, 0, 0};
return res;
}
//subTreeIndex 满节点的索引位置
void BTreeSplitChild(BTreeNode * paNode, int subTreeIndex)
{
struct BTreeNode * newNode = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
memset(newNode, 0, sizeof(struct BTreeNode));
struct BTreeNode * fullNode = paNode->subTree[subTreeIndex];
newNode->bLeaf = fullNode->bLeaf;
newNode->n = T - 1;
//将fullNode中后半部分的关键字赋给newNOde
for(int j=0;j<(T-1);++j)
{
newNode->keys[j] = fullNode->keys[j+T];
}
//将fullNode中后半部分的子节点赋给newNOde
if(!fullNode->bLeaf)
{
for(int j=0; j<T;++j) //2T个子节点
{
newNode->subTree[j] = fullNode->subTree[j+T];
}
}
fullNode->n = T - 1;
//父节点subTreeIndex之后的节点 向后移动
for(int j=paNode->n; j>subTreeIndex; j++)
{
paNode->subTree[j+1] = paNode->subTree[j];
}
paNode->subTree[subTreeIndex+1] = newNode; //将新生成的子节点填入父节点中
for(int j=paNode->n-1; j<subTreeIndex-1; --j)
{
paNode->keys[j+1] = paNode->keys[j];
}
paNode->keys[subTreeIndex] = fullNode->keys[T-1];
paNode->n++;
//DISKWRITE(fullNode)
//DISKWRITE(newNode)
//DISKWRITE(paNode)
}
void BTreeInsertNonFull(struct BTreeNode * node, BTreeKey k)
{
int i = node->n-1;
if(node->bLeaf)
{
//为k找到要插入的点
while(i>=0 && k<node->keys[i]) //从后向前找要插入的位置,同时向后移动键值.
{
node->keys[i+1] = node->keys[i];
i--;
}
node->keys[i+1] = k;
node->n++;
//DISKWRITE(node)
}
else
{
//确定子节点
while(i>=0 && k<node->keys[i])
i--;
i++;
//DiskRead(node->subTree[i])
if(node->subTree[i]->n == 2*T-1) //满了
{
BTreeSplitChild(node, i);
if(k > node->keys[i])
i++;
}
BTreeInsertNonFull(node->subTree[i], k);
}
}
void BTreeInsert(struct BTree * tree, BTreeKey k)
{
struct BTreeNode * r = tree->root;
if(r->n == (2*T-1))
{
struct BTreeNode * s = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
memset(s, 0, sizeof(struct BTreeNode));
tree->root = s;
s->bLeaf = FALSE;
s->n = 0;
s->subTree[0] = r;
BTreeSplitChild(s, 0);
BTreeInsertNonFull(s, k);
}
else
{
BTreeInsertNonFull(r, k);
}
}
void PrintTree(int kind, BTreeNode * pRoot); //打印树的关键字
int main()
{
struct BTree tree;
BTreeCreate(&tree);
BTreeInsert(&tree, 'A');
BTreeInsert(&tree, 'C');
BTreeInsert(&tree, 'G');
BTreeInsert(&tree, 'N');
BTreeInsert(&tree, 'H');
BTreeInsert(&tree, 'E');
BTreeInsert(&tree, 'K');
BTreeInsert(&tree, 'Q');
BTreeInsert(&tree, 'M');
BTreeInsert(&tree, 'F');
BTreeInsert(&tree, 'W');
BTreeInsert(&tree, 'L');
BTreeInsert(&tree, 'T');
BTreeInsert(&tree, 'Z');
BTreeInsert(&tree, 'D');
PrintTree(2, tree.root);
struct BTreeResult res = BTreeSearch(tree.root, 'M');
return 0;
}
///
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
/*
* 1 means integer
* 2 means character
*/
//PrintTree from https://github.com/gzc/CLRS/blob/master/C18-B-Trees/btree.cpp
void PrintTree(int kind, BTreeNode * pRoot) //打印树的关键字
{
queue<BTreeNode*> myqueue;
myqueue.push(pRoot);
int depth = 0;
cout << "c btree " << endl;
while(!myqueue.empty())
{
queue<BTreeNode*> nextlevel;
cout << "depth : " << depth << endl;
while(!myqueue.empty())
{
BTreeNode* temp = myqueue.front();
myqueue.pop();
cout << "[";
for(int i = 0;i <temp->n;i++)
{
if(kind == 2)cout << (char)temp->keys[i] << " ";
else cout << temp->keys[i] << " ";
}
cout << "]";
if(!temp->bLeaf)
for(int i = 0;i <temp->n+1;i++)
nextlevel.push(temp->subTree[i]);
}
cout << endl;
depth++;
myqueue = nextlevel;
}
}
c btree
depth : 0
[H ]
depth : 1
[C F ][N T ]
depth : 2
[A ][D E ][G ][K L M ][Q ][W Z ]