B-树的算法实现最难的还是插入操作和删除操作。就连生成B-树也依赖着插入操作。InsertBTree函数比较好的解决方法还是模块化- 将插入之后结点的数目变化分情况讨论,将复杂的逻辑结构拆分成 1、插入结点操作Insert 2、结点分裂操作Split 3、寻找插入相应的位置的操作Search 4、建立新的根节点的操作NewRoot 四个函数,具体应用到各种情况的讨论中。
删除函数需要注意的是指针域的挪动一个都不能马虎。因为连锁反应引起的删除虚拟结点并不是最后一层非终端结点。需要仔仔细细一个数据都不能漏。
此外由于根节点不是叶子结点(NULL)则至少需要两颗子树。不同于其他非终端结点需要(m/2)上限个,因此时时刻刻都需要单独讨论。
主要参考:http://www.cnblogs.com/kangjianwei101/p/5221816.html 自己根据理解加上了一些注释,略有微小的改动。
#ifndef B_TREE_H
#define B_TREE_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Base.h"
//B-Tree
//宏定义
#define M 3 //B树的阶
#define MAX_LEVEL 100
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
//类型定义
typedef ElemType_Search BTElemType;
typedef struct BTNode
{
int keynum; //结点中的关键字个数
struct BTNode *parent; //指向双亲结点
KeyType key[M+1]; //关键字向量,0号单元未用
struct BTNode *ptr[M+1]; //子树的指针向量
}BTNode; //B树的结点
typedef BTNode *BTree;
//查找结果类型
typedef struct
{
BTree pt; //指向找到的结点
int i; //关键字在结点中的序号,即插入位置
int tag; //1查找成功0查找失败
}Result;
//函数列表
Status CreateBTree (BTree *BT, Table T);
Result SearchBTree (BTree BT, KeyType k);
int Search (BTree p, KeyType k);
//返回k在结点p中的次序,若不存在返回0
Status InsertKey (BTree *BT, KeyType k);
//将关键字k插入树
Status InsertBTree (BTree *BT, KeyType k, BTree q, int i);
//插入算法,在结点*q的key[i]和key[i+1]之间插入关键字k
void Insert (BTree q, KeyType i, KeyType x, BTree ap);
//将x和ap分别插入到q->key[i+1]和q->ptr[i+1]中
void split (BTree q, int s, BTree *ap);
//以s为界,将q指向的结点分裂成q和ap指向的两部分
void NewRoot (BTree *BT, BTree q, int x, BTree ap);
//生成含信息(BT,x,ap)的新的根节点*BT,原BT和ap为子树指针,q初始值为NULL
Status DeleteKey (BTree *BT, KeyType k);
//从B树中删除关键字k
Status DeleteBTree (BTree *BT, BTree q, int i);
//从B树中删除结点q中的第i个关键字
void Delete (BTree *BT, BTree q, int i);
//从B树中删除结点q中的第i个关键字
Status SearchMinKey (BTree BT, Result *R);
//找出BT中最小的关键字
Status FoundParent (BTree q, BTree *p, int *order);
//寻找双亲结点,q为p的第i个孩子
Status LeftMove (BTree old_ptr, int m, BTree new_ptr, int n, int len);
//向左移动关键字和指针
Status RightMove (BTree old_ptr, int m, BTree new_ptr, int n, int len);
//向右移动关键字和指针
void PrintBT_Level (BTree BT);
//层序输出B树
void PrintBT_InOrder (BTree BT);
//中序输出B树
#endif // B_TREE_H
#ifndef B_TREE_C
#define B_TREE_C
#include "B-Tree.h"
//函数列表
Status CreateBTree (BTree *BT, Table T)
{
int i;
*BT = NULL;
if (T.length){
for (i=1;i<=T.length;i++){
if (!InsertKey(BT,T.elem[i].key))
break;
}
}
if (i>T.length)
return OK;
else
return ERROR;
}
Result SearchBTree (BTree BT, KeyType k)
{
Result R = {NULL,0,0};
BTree p,q;
int found,i;
p = BT;
q = NULL;
found = FALSE;
i=0;
while (p && !found){
i = Search(p,k);
if (i>0 &&p->key[i]==k)
found = TRUE;
else {
q = p;
p = p->ptr[i];
}
}
R.i = i;
if (found){
R.pt = p;
R.tag = 1;
} else {
R.pt = q;
R.tag = 0;
}
return R;
}
int Search (BTree p, KeyType k)
{
int i,j;
for (i=0,j=1;j<=p->keynum;j++){
if (p->key[j]<=k)
i = j;
else
break;
}
return i;
}
//返回k在结点p中的次序,若不存在返回0
Status InsertKey (BTree *BT, KeyType k)
{
Result R;
R = SearchBTree(*BT,k);
if (R.tag==1)
return ERROR;
else {
InsertBTree(BT,k,R.pt,R.i);
}
return OK;
}
//将关键字k插入树
Status InsertBTree (BTree *BT, KeyType k, BTree q, int i)
{
KeyType x = k;
BTree ap = NULL;
int finished = FALSE;
int s;
while (q && !finished){
Insert(q,i,x,ap); //将x和ap分别插入到q中
if (q->keynum<M)
finished = TRUE;
else {
//关键字数目超出限制
s = ceil((double)M/2); //除根节点之外至少有s棵子树,s-1个关键字
split(q,s,&ap); //以s为界分q为q和ap
x = q->key[s];