B树

/************************************************
 *作者:陈新
 *时间:2014 6.3
 *邮箱:cx2pirate@gmail.com
 * **********************************************/

#ifndef _HEADER_BTREE_
#define  _HEADER_BTREE_

#define N 5	//b-tree的度
#define TRUE 1
#define FALSE 0

typedef int BOOL;
typedef int Key;

typedef struct btree_node{				
	int count;
	BOOL is_leaf;
	Key key[2 * N - 1];
	struct btree_node *child[2 * N];
}btree_node,*btree_node_ptr;

typedef struct btree_root{
	struct btree_node *node;
	int height;	
}btree_root,*btree_root_ptr;

typedef struct btree_search_res{					//查询结果
	btree_node *node;
	int pos;
}btree_search_res;


btree_root *btree_create();
btree_search_res btree_search(btree_node *node,Key key);
void btree_insert(btree_root *root,Key key);
void btree_delete(btree_root *root,Key key);


#endif


#include "btree.h"
#include <stdio.h>
#include <stdlib.h>

//分配一个btree_node节点
btree_node *btree_node_alloc()
{		
	btree_node *node = (btree_node *)malloc(sizeof(btree_node));
	if(node == NULL){
		return NULL;
	}
	for(int i =0;i < 2 * N - 1;i++){
		node ->key[i] = 0;
	}
	for(int i = 0;i < 2 * N;i++){
		node ->child[i] = NULL;
	}
	node ->count = 0;
	node ->is_leaf = true;
	return node;
}

void btree_node_free(btree_node *node)
{
	free(node);
}

btree_root *btree_create()
{
	btree_root *root = (btree_root *)malloc(sizeof(btree_root));
	root ->node = btree_node_alloc();
	return root;
}

int btree_split_child(btree_node *parent,int pos,btree_node *child)
{
	btree_node *new_child = btree_node_alloc();
	if(new_child == NULL){
		return -1;
	}
	new_child ->is_leaf = child ->is_leaf;
	new_child ->count = N - 1;

	for(int i = 0;i < N - 1;i++){
		new_child ->key[i] = child ->key[i + N];
	}
	if(!child ->is_leaf){
		for(int i = 0;i < N;i++){
			new_child ->child[i] = child ->child[i + N];
		}
	}
	child ->count = N - 1;

	for(int i = parent ->count;i > pos;i--){
		parent ->child[i + 1] = parent ->child[i]; 
	}
	parent ->child[pos + 1] = new_child;

	for(int i = parent ->count - 1;i >= pos;i--){
		parent ->key[i + 1] = parent ->key[i];
	}
	parent ->key[pos] = child ->key[N - 1];
	parent ->count++;

	return 0;
}

void btree_insert_nonfull(btree_node *node,int key)
{
	if(node ->is_leaf){								//case1:插入叶子节点
		int pos = node ->count;
		while(pos >= 1 && key < node ->key[pos - 1]){
			node ->key[pos] = node ->key[pos - 1];
			pos--;
		}
		node ->key[pos] = key;
		node ->count++;
	}
	else{											//case2:递归插入
		int pos = node ->count;
		while(pos > 0 && key < node ->key[pos - 1]){
			pos--;
		}
		if(node ->child[pos] ->count == 2 * N - 1){
			btree_split_child(node,pos,node ->child[pos]);//分裂
			if(key > node ->key[pos]){					//选择新节点还是还是老节点
				pos++;
			}
		}
		btree_insert_nonfull(node ->child[pos],key);
	}
}

void btree_insert(btree_root *root,int key)
{
	if(root ->node == NULL){
		return;
	}	

	if(root ->node ->count == 2 * N - 1){		//分裂根节点
		btree_node *old_root = root ->node;
		root ->node = btree_node_alloc();
		root ->node ->is_leaf = FALSE;
		root ->node ->count = 0;
		root ->node ->child[0] = old_root;
		btree_split_child(root ->node,0,old_root);
	}
	btree_insert_nonfull(root ->node,key);
}
/***************************************************
 *删除部分
 *
 * ************************************************/
Key btree_maximum(btree_node *node)
{
	btree_node *p = node;
	while(!p ->is_leaf){
		p = p ->child[p ->count];
	}
	return p ->key[p ->count - 1];
}

Key btree_minimum(btree_node *node)
{
	btree_node *p = node;
	while(!p ->is_leaf){
		p = p ->child[0];
	}
	return p ->key[0];
}

/*pos左右两个孩子都只有N - 1个关键字,
 *把第pos个关键字,和两个孩子合并成一个
 *新的节点
 */
void btree_merge(btree_node *parent,int pos)
{
	btree_node *left_child = parent ->child[pos];
	btree_node *right_child = parent ->child[pos + 1];
	
	left_child ->key[N - 1] = parent ->key[pos];
	//for(int i = 0;i < N;i++)										//bug report
	for(int i = 0;i < N - 1;i++)									//竟然溢出覆盖了 ->child[0]
	{	
		left_child ->key[N + i] = right_child ->key[i];
	}
	if(!right_child ->is_leaf){
		for(int i = 0;i < N;i++){
			//left_child ->child[i] = right_child ->child[N + i];	//bug report
			left_child ->child[N + i] = right_child ->child[i];
		}
	}
	left_child ->count = 2 * N - 1;

	for(int i = pos + 1;i < parent ->count;i++){
		parent ->key[i - 1] = parent ->key[i];
		parent ->child[i] = parent ->child[i + 1];
	}
	parent ->count--;

	btree_node_free(right_child);
}

void shift_right_to_left(btree_node *parent,int pos)
{
	btree_node *child = parent ->child[pos];
	btree_node *right_child = parent ->child[pos + 1];

	child ->key[N - 1] = parent ->key[pos];
	parent ->key[pos] = right_child ->key[0];

	for(int i = 0;i < right_child ->count - 1;i++){
		right_child ->key[i] = right_child ->key[i + 1];
	}

	if(!right_child ->is_leaf){
		child ->child[N] = right_child ->child[0];
		for(int i = 0;i < right_child ->count;i++){
			right_child ->child[i] = right_child ->child[i + 1];
		}
	}

	child ->count++;
	right_child ->count--;
}
//
void shift_left_to_right(btree_node *parent,int pos)
{
	btree_node *child = parent ->child[pos];
	btree_node *left_child = parent ->child[pos - 1];

	//for(int i = 1;i <= child ->count;i++){					//bug report
	for(int i = child ->count;i > 0;i--){
		child ->key[i] = child ->key[i - 1];
	}
	//child ->key[0] = parent ->key[pos];						//bug report
	//parent ->key[pos] = left_child ->key[left_child ->count - 1];
	child ->key[0] = parent ->key[pos - 1];
	parent ->key[pos - 1] = left_child ->key[left_child ->count - 1];

	if(!left_child ->is_leaf){
		for(int i = child ->count + 1;i > 0;i--){
			child ->child[i] = child ->child[i - 1];
		}
		child ->child[0] = left_child ->child[left_child ->count];
	}

	child ->count++;
	left_child ->count--;
}

//node至少含有N个关键字的删除情况
void btree_delete_noback(btree_node *node,Key key)
{
	int pos = 0;
	while(pos < node ->count && node ->key[pos] < key){		//todo不存在的情况
		pos++;
	}
	if(pos < node ->count && node ->key[pos] == key){		//case1 && case2
		if(node ->is_leaf){									//case1
			for(int i = pos;i < node ->count - 1;i++){
				node ->key[i] = node ->key[i + 1];
			}
			node ->count--;
			return;
		}

		if(node ->child[pos] ->count >= N){						//case 2a
			Key pre = btree_maximum(node ->child[pos]);
			node ->key[pos] = pre;
			btree_delete_noback(node ->child[pos],pre);
		}
		else if(node ->child[pos + 1] ->count >= N){			//case 2b
			Key suc = btree_minimum(node ->child[pos + 1]);
			node ->key[pos] = suc;
			btree_delete_noback(node ->child[pos + 1],suc);
		}
		else{													//case 2c
			btree_merge(node,pos);
			btree_delete_noback(node ->child[pos],key);
		}
	}
	else{
		if(node ->is_leaf){										//case1 特殊情况,不存在节点
			return;
		}
		if(node ->child[pos] ->count == N - 1){
			btree_node *next = node ->child[pos];
			if(pos > 0 && node ->child[pos - 1] ->count >= N){					//case 3a_1
				shift_left_to_right(node,pos);
			}
			else if(pos < node ->count && node ->child[pos + 1] ->count >= N){	//case 3a_2
				shift_right_to_left(node,pos);
			}
			else if(pos > 0){
				btree_merge(node,pos - 1);
				next = node ->child[pos - 1];
			}
			else{
				btree_merge(node,pos);
			}
			btree_delete_noback(next,key);										//next may be wrong
		}
	}
}

//删除时需要更新root的情况,参考算法导论
//case 2c 和 case 3b
BOOL is_root_change(btree_root *root)
{
	return root ->node ->count == 1 &&
		root ->node ->child[0] ->count == N - 1 &&
		root ->node ->child[1] ->count == N - 1;
}

void btree_delete(btree_root *root,Key key)
{
	if(is_root_change(root)){
		btree_merge(root ->node,0);
		btree_node *old_root = root ->node;
		root ->node = root ->node ->child[0];
		btree_node_free(old_root);
	} 
	btree_delete_noback(root ->node,key);
}


/****************************************************
 *查找部分
 *
 * **************************************************/
//返回值...
btree_search_res btree_search(btree_node *node,int key)
{
	int pos = 0;
	while(pos < node ->count && key > node ->key[pos]){
		pos++;
	}
	if(pos < node ->count && key == node ->key[pos]){
		return btree_search_res{node,pos}; 								//return node and pos
	}
	if(node ->is_leaf){
		return btree_search_res{NULL,-1};
	}
	return btree_search(node ->child[pos],key);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值