B树代码实现

一棵m阶B树是一棵m路搜索树,它或者是空树,或者是满足以下性质的树:

1 根节点子女树为[2,m];

2 除根节点和叶节点以外所有分支结点至少有[m/2,m]个子女;

3 所有叶节点位于同一层。

B树的一些特点:

1 根节点关键字个数[1,m-1],非根节点关键字个数[m/2,m-1];

2 关键字集合分布在整棵树中;

3 关键字不容许重复;

4 搜索可能在非叶子结点结束;

5 搜索性能等价于在关键字全集做一次二分查找

#include<iostream>
#include<stdio.h>
#include<assert.h>
using namespace std;

const int M = 5;
const int MaxElemNum = M - 1;
const int MinElemNum = (M / 2);

typedef char KeyType;
typedef struct{} Record;
typedef struct
{
	KeyType key;
	Record* recptr;
}ElemType;

typedef struct BNode
{
	int num;
	struct BNode* parent;
	ElemType data[M + 1];
	struct BNode* sub[M + 1];
}BNode;
typedef struct
{
	BNode* root;
	int cursize;
}BTree;
typedef struct
{
	struct BNode* pnode;
	int index;
	bool tag;
}Result;
BNode* BuyNode()
{
	BNode* ptr = (BNode*)calloc(1, sizeof(BNode));
	if (ptr == nullptr) exit(EXIT_FAILURE);
	return ptr;
}
void FreeNode(BNode* ptr)
{
	free(ptr);
}
void InitTree(BTree* ptree)
{
	assert(ptree != nullptr);
	ptree->root = nullptr;
	ptree->cursize = 0;
}
Result FindKey(BTree* ptree, const KeyType kx)
{
	assert(ptree != nullptr);
	Result res = { nullptr,-1,false };
	BNode* p = ptree->root;
	while (p != nullptr)
	{
		int i = p->num;
		p->data[0].key = kx;
		while (kx < p->data[i].key) --i;
		res.pnode = p;
		res.index = i;
		if (i > 0 && p->data[i].key == kx)
		{
			res.tag = true;
			break;
		}
		p = p->sub[i];
	}
	return res;
}
BNode* MakeRoot(ElemType item, BNode* left, BNode* right)
{
	BNode* s = BuyNode();
	s->num = 1;
	s->parent = nullptr;
	s->data[1] = item;
	s->sub[0] = left;
	if (left != nullptr) left->parent = s;
	s->sub[1] = right;
	if (right != nullptr) right->parent = s;
	return s;
}
void Insert_Item(BNode* ptr, int pos, ElemType item, BNode* right)
{
	assert(ptr != nullptr);
	for (int i = ptr->num; i > pos; --i)
	{
		ptr->data[i + 1] = ptr->data[i];
		ptr->sub[i + 1] = ptr->sub[i];
	}
	ptr->data[pos + 1] = item;
	ptr->sub[pos + 1] = right;
	if (right != nullptr) right->parent = ptr;
	ptr->num += 1;
}
ElemType Move_Item(BNode* ptr, BNode* right)
{
	assert(ptr != nullptr && right != nullptr);
	for (int i = MinElemNum + 1, j = 0; i <= ptr->num; ++i, ++j)
	{
		right->data[j] = ptr->data[i];
		right->sub[j] = ptr->sub[i];
		if (right->sub[j] != nullptr)
		{
			right->sub[j]->parent = right;
		}
	}
	ptr->num = MinElemNum;
	right->num = MinElemNum;
	right->parent = ptr->parent;
	return right->data[0];
}
BNode* Adjust_Tree(BTree* ptree, BNode* ptr)
{
	assert(ptree != nullptr && ptr != nullptr);
	BNode* right = BuyNode();
	ElemType item = Move_Item(ptr, right);
	if (ptr->parent == nullptr)
	{
		return MakeRoot(item, ptr, right);
	}
	BNode* pa = ptr->parent;
	int pos = pa->num;
	pa->data[0] = item;
	while (item.key < pa->data[pos].key) --pos;
	Insert_Item(pa, pos, item, right);
	if (pa->num > MaxElemNum)
	{
		return Adjust_Tree(ptree, pa);
	}
	else
	{
		return nullptr;
	}
}
bool Insert(BTree* ptree, ElemType item)
{
	assert(ptree != nullptr);
	if (ptree->root == nullptr)
	{
		ptree->root = MakeRoot(item, nullptr, nullptr);
		ptree->cursize = 1;
		return true;
	}
	Result res = FindKey(ptree, item.key);
	if (res.tag) return false;
	BNode* ptr = res.pnode;
	int pos = res.index;
	Insert_Item(ptr, pos, item,nullptr);
	if (ptr->num > MaxElemNum)
	{
		BNode* newroot = Adjust_Tree(ptree, ptr);
		if (newroot != nullptr)
		{
			ptree->root = newroot;
		}
	}
	ptree->cursize += 1;
	return true;
}
void InOrder(BNode* ptr)
{
	if (ptr == nullptr) return;
    InOrder(ptr->sub[0]);
	for(int i = 1; i <= ptr-> num;++i)
	{
		printf("%3c",ptr->data[i].key);
	    InOrder(ptr->sub[i]);
	}
}
void InOrder(BTree* ptree)
{
	assert(ptree != nullptr);
	InOrder(ptree->root);
	printf("\n");
}

int main()
{
	KeyType ar[] = { "q9wer6tyui0o1pa7sd4fghj2kl5z80xcvb3nm" };

	int len = strlen(ar);
	BTree tree;
	InitTree(&tree);
	for (int i = 0; i < len; ++i)
	{
		ElemType item = { ar[i],nullptr };
		cout << Insert(&tree, item);
	}
	cout << endl;
	InOrder(&tree);
	
	return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值