B樹 寫文件

#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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章