B树和B树的实现 B-Tree

根据算法导论的描述。B树是一种特殊的平衡树和查找树。其主要用于磁盘内数据的存储和查找。因此,B树一般每个结点会比较大,包含许多数据关键字,最好占一个页面(page),这样存取的时候直接存取一个结点的数据。


B树的基本性质(M阶):

1、B树的每个叶子节点的高度均一致。

2、对于非空B树,普通非根非叶节点至少有M-1个关键字(M个子女),至多2M-1个关键字(2M个子女)。根节点至少包含2个子女(因为根节点只有1个关键字时,要有两个对应的孩子指针)。

3、结点内部的数据关键字是按从小到大排序的。


B树的结点的结构(M阶):

typedef struct btree_node
{
	int k[2*M-1];		//用于存储数据关键字
	btree_node *p[2*M];	//用于存储指向孩子的指针
	int num;	// 当前结点内数据关键字的个数, <=2*M-1
	bool is_leaf;	// 当前结点是否是叶子结点 true/false
}btree_node,*btree;

B树操作上的特质:

1、插入新数据关键字总是要往叶子结点上插入。

2、插入操作所造成的B树的扩张,使得树的高度升高一定是在根节点增加高度的。(这是由插入操作的手段所决定。)


B树结点的创建:

btree init_btree_node()
{
	btree_node *node = (btree_node*)malloc(sizeof(btree_node));
	if(node ==NULL)
		return NULL;
	for(int i=0;i<2*M-1;i++)
		node->k[i] = 0;
	for(int i=0;i<2*M;i++)
		node->p[i] = NULL;
	node->num = 0;
	node->is_leaf = true;
	return node;
}


在写如何插入新的数据关键字之前,先考虑一个结点如何分裂:

//child结点满了,一分为二: 0~M-2  M-1  M~2M-2 
//   1
//M-1 M-1
int split_child(btree parent, int pos, btree child)
{
	//create a new child node for the other M-1 keys
	btree_node *new_child = init_btree_node();
	if(new_child == NULL)
		return -1;
	new_child->is_leaf = child->is_leaf;
	new_child->num = M-1;
	for(int i=0;i<M-1;i++)
		new_child->k[i] = child->k[i+M];
	if(new_child->is_leaf == false)
		for(int i=0;i<M;i++)
			new_child->p[i] = child->p[i+M];

	//adjust the former child node
	child->num = M-1;

	//adjust parent node
	for(int i=parent->num; i>pos;i--)
		parent->p[i+1] = parent->p[i];
	parent->p[pos+1] = new_child; 

	for(int i=parent->num-1;i>=pos;i--)
		parent->k[i+1] = parent->k[i];
	parent->k[pos] = child->k[M-1];
	parent->num ++;

	return 1;
}


对B树新关键字插入的实现是个特别的过程,从根结点向下追溯到叶子结点,途中遇到满的结点需要分裂:

--对根节点执行btree_insert();

--如果根节点满了,B树需要升高一层;

--向其孩子结点插入,遇到满结点需要分裂,逐步递归到叶子结点。

btree btree_insert(btree root, int target)
{
	if(root == NULL)
		return NULL;
	if(root->num == 2*M-1)
	{
		//create new root
		//the only way to add the height of btree 
		btree_node *node = init_btree_node();
		if(node == NULL)
			return NULL;
		node->is_leaf = false;
		node->p[0] = root;
		split_child(node, 0, root);
		btree_insert_nonfull(node, target);
		return node;
	}
	else
	{
		btree_insert_nonfull(root, target);
		return root;
	}
}

void btree_insert_nonfull(btree node, int target)
{
	if(node->is_leaf == true)
	{
		int pos = node->num;
		while(pos>=1 && target < node->k[pos-1])
		{
			node->k[pos] = node->k[pos-1];
			pos--;
		}
		node->k[pos] = target;
		node->num ++; 
	}
	else
	{
		int pos = node->num;
		while(pos>0 && target < node->k[pos-1])
			pos--;
		if(node->p[pos]->num == 2*M-1)
		{
			split_child(node, pos, node->p[pos]);
			if(target > node->k[pos])
				pos++;
		}
		btree_insert_nonfull(node->p[pos], target);
	}
}


B树的删除操作:

未完成,有待学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值