B树 写文件
程序员文章站
2022-05-18 16:54:45
...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAX_OFF_T ((off_t)-1)
#define MAX_NODE 15
#define MID_NODE (MAX_NODE/2)
#define LEFT_SIZE (MID_NODE)
#define RIGHT_SIZE (MAX_NODE - MID_NODE - 1)
int search(int* nums,int left,int right,int target)//核心函数
{
if(left > right)
return left;
int middle = (left+right)/2;
if(nums[middle] == target)
{
return middle;
}
if(nums[middle] > target)
{
return search(nums,left,middle-1,target);
}
else
{
return search(nums,middle+1,right,target);
}
}
typedef struct{
int keyNum;//most is m-1
int key[MAX_NODE];//most is m-1
int value[MAX_NODE];//most is m-1
off_t next[MAX_NODE+1];//most is m
off_t parent;
}BTNode;
void init_node(BTNode *node)
{
node->keyNum = 0;
memset(node->next,0xff,sizeof(node->next));//等效MAX_OFF_T
node->parent = MAX_OFF_T;
}
int update_node(int fd,BTNode *node,off_t offset)
{
//lseek(fd,offset,SEEK_SET);
//write(fd,node,sizeof(BTNode));
pwrite(fd,node,sizeof(BTNode),offset);
fsync(fd);
}
int update_child_node(int fd,BTNode *node,off_t offset)
{
int i;
BTNode node_child;
for(i=0;i<=node->keyNum;i++)
{
if(node->next[i] == MAX_OFF_T)
continue;
//lseek(fd,node->next[i],SEEK_SET);
//read(fd,&node_child,sizeof(BTNode));
pread(fd,&node_child,sizeof(BTNode),node->next[i]);
node_child.parent = offset;
//lseek(fd,sizeof(BTNode)*(-1),SEEK_CUR);
//write(fd,&node_child,sizeof(BTNode));
pwrite(fd,&node_child,sizeof(BTNode),node->next[i]);
}
fsync(fd);
}
int balance(int fd)
{
BTNode node;
BTNode node_parent;
BTNode node_brother;
off_t offset;
off_t offset_parent;
off_t offset_brother;
int index;
if(read(fd,&node,sizeof(BTNode)) == 0)
{
return fd;
}
offset = lseek(fd,sizeof(BTNode)*(-1),SEEK_CUR);
if(node.keyNum < MAX_NODE)//个数少 不进行balance
{
return fd;
}
if(node.parent == offset)//如果父母是自己 则生成新的父节点 生成新的兄弟节点 !!此时offset == 0
{
//写brother
init_node(&node_brother);
memcpy(node_brother.key,&node.key[MID_NODE+1],sizeof(int)*RIGHT_SIZE);
memcpy(node_brother.value,&node.value[MID_NODE+1],sizeof(int)*RIGHT_SIZE);
memcpy(&node_brother.next,&node.next[MID_NODE+1],sizeof(off_t)*(RIGHT_SIZE+1));
node_brother.keyNum = RIGHT_SIZE;
node_brother.parent = 0;//offset_parent
offset_brother = lseek(fd,0,SEEK_END);
//更新兄弟节点的parent
update_child_node(fd,&node_brother,offset_brother);
//更新兄弟
update_node(fd,&node_brother,offset_brother);
//更新自己
node.keyNum = LEFT_SIZE;
node.parent = 0;//offset_parent
offset = offset_brother + sizeof(BTNode);
//更新自己节点的parent
update_child_node(fd,&node,offset);
//更新自己
update_node(fd,&node,offset);
//写parent
init_node(&node_parent);
node_parent.keyNum = 1;
node_parent.key[0] = node.key[MID_NODE];
node_parent.next[0] = offset;
node_parent.next[1] = offset_brother;
offset_parent = 0;
node_parent.parent = offset_parent;
update_node(fd,&node_parent,offset_parent);
lseek(fd,offset_parent,SEEK_SET);
return fd;
//返回parent
}
else//如果父母不是自己 中间的兄弟上父节点 生成新的兄弟节点
{
offset_parent = node.parent;
pread(fd,&node_parent,sizeof(BTNode),offset_parent);
//写brother
init_node(&node_brother);
memcpy(node_brother.key,&node.key[MID_NODE+1],sizeof(int)*RIGHT_SIZE);
memcpy(node_brother.value,&node.value[MID_NODE+1],sizeof(int)*RIGHT_SIZE);
memcpy(&node_brother.next,&node.next[MID_NODE+1],sizeof(off_t)*(RIGHT_SIZE+1));
node_brother.keyNum = RIGHT_SIZE;
node_brother.parent = offset_parent;
offset_brother = lseek(fd,0,SEEK_END);
//更新兄弟节点的parent
update_child_node(fd,&node_brother,offset_brother);
//写兄弟
update_node(fd,&node_brother,offset_brother);
//写自己
node.keyNum = LEFT_SIZE;
node.parent = offset_parent;
//更新自己节点的parent
//update_child_node(fd,&node,offset);
//写自己
update_node(fd,&node,offset);
//写parent
index = search(node_parent.key,0,node_parent.keyNum-1,node.key[MID_NODE]);
if(index != node_parent.keyNum)
{
memmove(&node_parent.key[index+1],&node_parent.key[index],sizeof(int) * (node_parent.keyNum-index));
memmove(&node_parent.value[index+1],&node_parent.value[index],sizeof(int) * (node_parent.keyNum-index));
memmove(&node_parent.next[index+1],&node_parent.next[index],sizeof(off_t) * (node_parent.keyNum-index+1));
}
node_parent.key[index] = node.key[MID_NODE];
node_parent.value[index] = node.value[MID_NODE];
node_parent.next[index] = offset;
node_parent.next[index+1] = offset_brother;
node_parent.keyNum++;
update_node(fd,&node_parent,offset_parent);
//返回自己
lseek(fd,offset,SEEK_SET);
return fd;
}
}
int putValue(int fd,int key,int val){
BTNode node;
off_t offset;
int index;
if(read(fd,&node,sizeof(BTNode)) == 0)
{
init_node(&node);
node.keyNum = 1;
node.key[0] = key;
node.value[0] = val;
node.parent = 0;
offset = 0;
update_node(fd,&node,offset);
lseek(fd,offset,SEEK_SET);
return fd;
}
offset = lseek(fd,sizeof(BTNode)*(-1),SEEK_CUR);
index = search(node.key,0,node.keyNum-1,key);
if(node.key[index] == key)
{
node.value[index] = val;
update_node(fd,&node,offset);
lseek(fd,offset,SEEK_SET);
return fd;
}
if(node.next[index] == MAX_OFF_T)//没有子树 最底层
{
if(index != node.keyNum)
{
memmove(&node.key[index+1],&node.key[index],sizeof(int) * (node.keyNum-index));
memmove(&node.value[index+1],&node.value[index],sizeof(int) * (node.keyNum-index));
}
node.key[index] = key;
node.value[index] = val;
node.keyNum++;
update_node(fd,&node,offset);
}
else
{
lseek(fd,node.next[index],SEEK_SET);
putValue(fd,key,val);
}
lseek(fd,offset,SEEK_SET);
balance(fd);
return fd;
}
void showTree(int fd){
BTNode node;
off_t offset;
int i;
if(read(fd,&node,sizeof(BTNode)) == 0)
{
return;
}
offset = lseek(fd,sizeof(BTNode)*(-1),SEEK_CUR);
for(i=0;i<node.keyNum;i++)
{
if(node.next[i] != MAX_OFF_T)
{
lseek(fd,node.next[i],SEEK_SET);
showTree(fd);
}
printf("%d ",node.key[i]);
}
if(node.next[i] != MAX_OFF_T)
{
lseek(fd,node.next[i],SEEK_SET);
showTree(fd);
}
}
#if 1
int main()
{
int fd = open("dat",O_RDWR|O_CREAT|O_TRUNC,0664);
srand(time(NULL));
int i,j;
int *n;
int number = 10000;
n = malloc(sizeof(int)*number);
for(i=0;i<number;i++)
{
n[i] = i;
}
for(i=number;i > 0;i--){
j = rand()%i;
//printf("%d\n",n[j]);
putValue(fd,n[j],n[j]);
n[j] = n[i-1];
}
close(fd);
fd = open("dat",O_RDONLY,0664);
if(fd < 0)
return;
showTree(fd);
close(fd);
}
#else
int main()
{
int fd = open("dat",O_RDONLY,0664);
if(fd < 0)
return;
showTree(fd);
close(fd);
}
#endif
上一篇: 为什么数据库索引使用B+树实现
下一篇: JAVA保留2位有效数字