欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

 

相关标签: C B树