没有合适的资源?快使用搜索试试~ 我知道了~
B+树代码实现
资源推荐
资源详情
资源评论
//by svking
//2012.5
/****************************************************************
B+树的实现。这个 B+树是建立在操作系统的文件系统之上的,并没有自己的文件系
统。
B+树的节点全部存储在一个文件中。由于每个节点的大小是相同的,所以我对每个节点
进 行 编 号 , 即 每 个 节 点 的 id 。 这 样 每 个 节 点 在 文 件 的 字 节 位 置 就 可 以 通 过 计 算
sizeof(BPNode)*(c->id - 1)得到。
所以,每个 B+树的节点有一个 id 属性,就是记录自己的标号。
同时对 B+树建立一个结构体,这个结构体中的 root 属性,用于指向读入内存后的树的
根节点。
locate 属性记录树的根节点的在文件中的标号。num 属性记录这棵树的节点个数,每次新
增一个节点都会加一。
name 属性记录用于存储这个 B+树的文件名(相对 cpp 文件所在的文件夹),fp 属性用于
记录打开这个文件时的文件指针
因为这个文件只记录 B+树的节点,所以每次插入的时候只需要直接插入最后(只有
num 个节点,同时新插入的节点的 id 是 num+1)
暂时不考虑删除节点的文件空间回收。
*****************************************************************/
/
*******************************************************************************
************************
打开文件是要注意打开模式,r+模式可以才可以随意用 fseek()定位之后,读或写。
fseek()和 fread()和 fwrite()是用于二进制打开的文件,如果文本模式打开,可能出现问题,
如:覆盖。
*******************************************************************************
************************/
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#define T 3 //b+树的度数
#define KeyType int
#define Pointer int
//节点结构体
typedef struct BPNode
{
unsigned int id;//记录这个节点在文件的中的编号
unsigned int n;//记录这个节点有多少个关键字
int leaf; //判断是否为页节点
KeyType key[2*T];//关键字(及对应每个孩子节点的中关键字最小的关键字)
Pointer child[2*T];//指针,记录每个孩子在文件的第几个位置
Pointer next;//指针,,记录下一个兄弟
}BPNode,*P_BPNode;
//树的结构体
typedef struct BPTree
{
P_BPNode root;
unsigned int locate;//记录根节点的在文件中的标号,即 id
unsigned int num; //记录更有多少个节点
char name[100]; //用于存储 B+树的节点文件的名字
FILE *fp; //打开写入 name 文件时,使用
int start; //最小的数据所在的叶节点
}BPTree,*P_BPTree;
BPTree indexBPTree; //全局变量,b+树
int writeNode(P_BPNode w)
{
fseek(indexBPTree.fp, sizeof(BPNode)*(w->id - 1) + 2*sizeof(int), SEEK_SET);
fwrite(w, sizeof(BPNode),1,indexBPTree.fp);
return 0;
}
int readNode(P_BPNode r, Pointer id)
{
fseek(indexBPTree.fp, (sizeof(BPNode))*(id - 1) + 2*sizeof(int), SEEK_SET);
fread(r, (sizeof(BPNode)),1,indexBPTree.fp);
return 0;
}
int pNode(P_BPNode n);
int createIndexBPTree (char *tableName, char *attr)
{//创建 B+树,并进行相应的初始化,B+树的结构体是一个全局变量。
P_BPNode root;
indexBPTree.root = (P_BPNode)malloc(sizeof(BPNode));
indexBPTree.num = 1;
indexBPTree.start = 1;
memcpy(indexBPTree.name, ".\\table\\", sizeof(".\\table\\"));
strcat(indexBPTree.name, tableName);
strcat(indexBPTree.name, ".");
strcat(indexBPTree.name, attr);
puts(indexBPTree.name);
root = indexBPTree.root;
root->n = 0;
root->leaf = 1;
root->next = -1;
root->id = 1;
indexBPTree.locate = 1;
indexBPTree.fp = fopen(indexBPTree.name, "wb");
fwrite(&indexBPTree.num, sizeof(int),1,indexBPTree.fp);
fwrite(&indexBPTree.locate, sizeof(int),1,indexBPTree.fp);
writeNode(root);
fclose(indexBPTree.fp);
/*
printf("原始:%d\n", indexBPTree.root->next);
memset(indexBPTree.root,0,sizeof(BPNode));
printf("memset 后:%d\n", indexBPTree.root->next);
indexBPTree.fp = fopen(indexBPTree.name,"r");
fread(indexBPTree.root, sizeof(BPNode),1,indexBPTree.fp);
fclose(indexBPTree.fp);
printf("读取文件后:%d\n", indexBPTree.root->next);
*/
free(root);
indexBPTree.root = NULL;
return 0;
}
int splitBPNode (P_BPNode p, P_BPNode c, int i)
{//节点的分裂,要求 p 节点至少还能插入一个节点,c 节点是满的,即 n 为 2*T;
int j;
P_BPNode b;
b = (P_BPNode)malloc(sizeof(BPNode));
b->leaf = c->leaf;
b->n = T;
b->id = indexBPTree.num+1; //为 b 赋值 id 号,用于表示该节点,,同时 id 号就是这个
节点在文件的位置
b->next = c->next; //为 b 的 next 赋值,即原来的 c 节点的 next
//将 c 节点的后半部分关键字复制给 b
for (j = 0; j < T; j++)
{
b->key[j] = c->key[j+T];
b->child[j] = c->child[j+T];
}
//至此 b 节点的对应元素已经建立好了,但还需要写入文件
indexBPTree.num++;
c->n = T; //c 节点的关键字数目减半
c->next = b->id;
//将 p 节点的 i 之后的节点后移
for (j = p->n - 1; j > i; j--)
{
p->key[j+1] = p->key[j];
p->child[j+1] = p->child[j];
}
//将 b 节点插入 p 中
p->key[i+1] = b->key[0];
p->child[i+1] = b->id;
p->n++; //p 关键字个数加一
//写入 p
writeNode(p);
writeNode(c);
writeNode(b);
free(b);
return 0;
}//splitBPNode
int insertBPNodeNotFull(P_BPNode s, KeyType k, unsigned int id)
{//插入,要求 s 节点不是满的
int i = s->n-1;
if (s->leaf)
{//叶节点,找的合适的位置
while (i >= 0 && s->key[i] > k)
{
剩余15页未读,继续阅读
资源评论
yzu_120702117
- 粉丝: 99
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功