B树基本操作C实现

昨天研究后缀数组和后缀树,发现将后缀树的建立第一个拉低到接近线性时间的Edward McCreigh竟然就是B-Tree的发明者之一。

B-Tree的另一个发明者bayer居然还是红黑树的发明者,简直是树精。

想想虽然B-Tree的原理是了解的,但是还从来没有自己写过B树的实现。

diors的星期天晚上是如此的寂寞空虚,实在找不到事情可以做,试着写写看。


/*************************************************************
 * file:btree_operation.c
 * brief:operations of b_tree(included build/search/insert/delete)
 * yejing@2015.1.25    1.0      create
 *************************************************************/
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
 /*2,3,4树*/
 #define btree_dg 2
 #define CHILD_NUM  2 * btree_dg
 #define KEY_NUM    2 * btree_dg - 1
 
 
 typedef struct _btree_t{
	int key_count;
	int key[KEY_NUM];
	struct _btree_t* child[CHILD_NUM];
	int is_leaf;
 }btree_t;
 
 static btree_t* allocate_btree_node(void){
	btree_t* node = (btree_t*)malloc(sizeof(btree_t));
	if(!node)
		assert(0);
	memset((char*)node, 0, sizeof(btree_t));
	
	return node;
 }
 
 btree_t* build_a_btree(void){
	btree_t* root = allocate_btree_node();
	if(!root)
		assert(0);
	root->is_leaf = 1;
	
	return root;
 }
 
 btree_t* btree_search(btree_t* root, int key){
	int i = 0;
	while(i < root->key_count && key > root->key[i])
		++i
	if(i < root->key_count && key = root->key[i])
		return root;
		
	if(root->is_leaf)
		return NULL;
	else
		return btree_search(root->child[i], key);
 }
 
 /*
 child是一个满节点,它是其父亲father的第child_index+1个孩子。
 btree_split_child将child按其中间关键字分裂成两个btree_dg-1的子树。
 同时将其中间关键字上浮到father中。
 此函数从根节点由上向下调用,所以father肯定不会是满的。
 */
 void btree_split_child(btree_t* father, btree_t* child, int child_index){
	if(!father || !child || child_index < 0 || child_index + 1 > CHILD_NUM)
		assert(0);
	
	int i = 0;
	//新建一个tmp节点,用于收养child中较大的一半子女
	btree_t* tmp = allocate_btree_node();
	if(!tmp)
		assert(0);
	
	//如果child是叶节点,tmp也应该是叶节点
	tmp->is_leaf = child->is_leaf;
	
	//调整tmp和child的关键字计数
	tmp->key_count = btree_dg - 1;
	child->key_count = btree_dg - 1;
	
	//将child后面一半较大的关键字赋给tmp
	for(i = 0; i < btree_dg - 1; ++i)
		tmp->key[i] = child[btree_dg + i];
	
	//如果child不是叶节点,tmp将收养其后半部分孩子
	if(!child->is_leaf)
		for(i = 0; i < btree_dg; ++i)
			tmp->child[i] = child[btree_dg + i];
			
	//调整father的child指针数组位置,给tmp留出空间,并将tmp托管给father
	for(i = father->key_count; i > index; --i)
		father->child[i + 1] = father->child[i];
	father->child[index + 1] = tmp;
			
	//将child的中间关键值上浮给father
	for(i = father->key_count - 1; i > index - 1; --i)
		father->key[i + 1] = father->key[i];
	father->key[index] = child->[btree_dg - 1];
	
	//最后修改father的keycount
	father->key_count++;
	return;
 }
 
 /*
 将key插入到node中,基于node不是满的。
 在需要时会沿着树向下递归,必要的时候调用btree_split_child分割节点
 */
 void btree_insert_nonfull(btree_t* node, int key){
	if(!node)
		assert(0);
	
 }
 
 btree_t* btree_insert(btree_t* root, int key){
	if(!root)
		assert(0);
		
	btree_t* tmp = root;
	//节点满
	if(tmp->key_count == KEY_NUM){
		btree_t* tmp1 = allocate_btree_node();
		if(!tmp1)
			assert(0);
			
		root = tmp1;
		tmp1->is_leaf = 0;
		tmp1->key_count = 0;
		tmp1->child[0] = tmp;
		btree_split_child(tmp1, 0, root);
		btree_insert_nonfull(tmp1, key);
	}
	else{
		btree_insert_nonfull(tmp, key)
	}
 }
    原文作者:B树
    原文地址: https://blog.csdn.net/yejing_utopia/article/details/43126831
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞