B树(插入,删除)

B树

B-tree树,一个m阶B数
目录结构
1.根节点子女数为[2,m],m必须是奇数
2.除根结点和叶节点以外的所有分支节点至少右[[m/2],m]个子女
3.所有节点都位于同一层。(天生就是平衡树)
4.m阶B-tree树的节点结构如下
在这里插入图片描述

B树的插入

父节点大于左边的子节点,小于右边的子节点。能放数据的只有1,2,3,4. 0号位置是哨兵位,先存在这里面然后和后面的比较啊
父子都有6个节点,0是存刚插入的数据,确定位置后插入,父节点最多存4个节点,当多余4个节点时候就分裂成三个,两个在左两个在右,中间的在上面,如下图
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
num这一层有几个数据,parent它的父节点是谁,k[0]是一个哨兵位,k[1]大于sub[0]指针指向的数据值,
在这里插入图片描述
在这里插入图片描述

B树的删除

m=5
m/2=2

从叶子开始删除,要删除那个节点,就把这个节点和它的直接前驱将这个节点改成直接前驱的值(只有当直接前驱的数据大于(m/2)个的时候才互换),然后删除它的叶子节点,如果直接前驱少于(m/2)个,就找他的直接后继(当直接后继多于(m/2)个的时候),将后继的值赋值给那个节点,删除完之后需要移动数据
如果删除的不够了,就先将这个节点左边的值移动过来,如果左边的值也不够了,再移动右边的值,移动的时候先把移动根节点移下来,再将根节点左边的值移上去,右边同理
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
如果删除到最后左右两边都只剩两个了,删除掉之后合并,把根节点移到左边,再把右边的数据都移到左边,如下图
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

无论是借数据还是合并数据,都是先左后右

#define  M  5   //  M 奇数 // 
#define  BRCHMAX    (M-1) //  // SUB M 
#define  BRCHMIN    (M/2);	  // SUB M/2+1

#define  LEAFMAX (M)   // MAX ELEM	 5
#define  LEAFMIN (M/2+1)   // MIN ELEM; 3 

typedef int KeyType;
typedef struct {}Record;
typedef enum { BRCH = 1, LEAF = 2 } NodeType;

typedef struct BNode
{
	int num; // elem size; // LEFT BRCH
	BNode* parent;
	NodeType utype; // LEAF , BRCH;	
	KeyType key[M + 1];
	union
	{
		struct	// LEAF
		{
			Record* recptr[M + 1];
			BNode* prev, * next;
		};
		// BRCH;  
		BNode* sub[M + 1];
	};
}BNode;
typedef struct
{
	struct BNode* root;
	struct BNode* first;
	int cursize;
}BTree;

typedef struct
{
	struct BNode* pnode;	// 
	int index;			//
	bool tag;			//
}Result;

BNode* Buynode()
{
	BNode* s = (BNode*)malloc(sizeof(BNode));
	if (nullptr == s) exit(1);
	memset(s, 0, sizeof(BNode));
	return s;
}

BNode* BuyLeaf()
{
	BNode* s = Buynode();
	s->parent = nullptr;
	s->utype = LEAF;
	return s;
}
BNode* BuyBrchnode()
{
	BNode* s = Buynode();
	s->parent = nullptr;
	s->utype = BRCH;
	return s;
}
void Init_BTree(BTree& tree)
{
	tree.root = nullptr;
	tree.first = nullptr;
	tree.cursize = 0;
}

BNode* MakeRoot(const KeyType kx, BNode* left, BNode* right)
{
	BNode* s = Buynode();
	s->utype = BRCH;
	s->num = 1;
	s->parent = nullptr;
	s->key[1] = kx;
	s->sub[0] = left;
	if (left != nullptr) left->parent = s;
	s->sub[1] = right;
	if (right != nullptr) right->parent = s;
	return s;
}
Result FindLeaf(BNode* ptr, KeyType kx)
{
	Result res = { nullptr,-1,false };
	BNode* p = ptr;
	while (p != nullptr && p->next != nullptr && kx > p->key[p->num - 1])
	{
		p = p->next;
	}
	if (p == nullptr) return res;
	int pos = p->num - 1;
	while (pos >= 0 && kx < p->key[pos])
	{
		--pos;
	}
	res.pnode = p;
	res.index = pos;
	if (pos < 0 && p->prev != nullptr)
	{
		res.pnode = p->prev;
		res.index = p->prev->num - 1;
	}
	else 	if (pos >= 0 && kx == p->key[pos])
	{
		res.tag = true;
	}
	return res;
}

Result FindRoot(BNode* ptr, KeyType kx)
{
	Result res = { nullptr,-1,false };
	BNode* p = ptr;
	while (p != nullptr && p->utype == BRCH)
	{
		p->key[0] = kx;
		int i = p->num;
		while (kx < p->key[i]) --i;
		p = p->sub[i];
	}
	
	res = FindLeaf(p, kx);
	return res;
}

void Insert_Leaf_Item(BNode *ptr,int  pos,KeyType  kx, Record *rec)
{
	for (int i = ptr->num - 1; i > pos; --i)
	{
		ptr->key[i + 1] = ptr->key[i];
		ptr->recptr[i + 1] = ptr->recptr[i];
	}
	ptr->key[pos + 1] = kx;
	ptr->recptr[pos + 1] = rec;
	ptr->num += 1;
}
KeyType Move_Leaf_Item(BNode* s, BNode* ptr)
{
	for (int i = 0, j = LEAFMIN; j < ptr->num; ++i, ++j)
	{
		s->key[i] = ptr->key[j];
		s->recptr[i] = ptr->recptr[j];
	}
	s->num = LEAFMIN;
	ptr->num = LEAFMIN;
	s->parent = ptr->parent;
	s->next = ptr->next;
	s->prev = ptr;
	ptr->next = s;
	if (s->next != nullptr)
	{
		s->next->prev = s;
	}
	return s->key[0];
}
void Insert_Brch_Item(BNode* ptr, int pos, KeyType kx, BNode* right)
{
	for (int i = ptr->num; i > pos; --i)
	{
		ptr->key[i + 1] = ptr->key[i];
		ptr->sub[i + 1] = ptr->sub[i];
	}
	ptr->key[pos + 1] = kx;
	ptr->sub[pos + 1] = right;	 // right->parent;
	ptr->num += 1;
}

KeyType Move_Brch_Item(BNode* s, BNode* ptr)
{
	for (int i = 0, j = LEAFMIN + 1; j <= ptr->num; ++i, ++j)
	{
		s->key[i] = ptr->key[j];
		s->sub[i] = ptr->sub[j];
		if (s->sub[i] != nullptr)  // ptr leaf . brch;
		{
			s->sub[i]->parent = s;
		}
	}
	s->num = LEAFMIN;
	ptr->num = LEAFMIN;
	s->parent = ptr->parent;
	return s->key[0];
}
BNode* Splice_Brch(BNode* ptr)
{
	BNode* s = BuyBrchnode();
	KeyType kx = Move_Brch_Item(s, ptr);
	if (ptr->parent == nullptr)
	{
		return MakeRoot(kx, ptr, s);
	}

	BNode* pa = ptr->parent;
	int pos = pa->num;
	pa->key[0] = kx; //
	while (pos > 0 && kx < pa->key[pos]) { --pos; }
	Insert_Brch_Item(pa, pos,kx, s);
	if (pa->num > LEAFMAX)
	{
		return Splice_Brch(pa);
	}
	else
	{
		return nullptr;
	}
}
BNode* Splice_Leaf(BNode* ptr)
{
	BNode* s = BuyLeaf();
	KeyType kx = Move_Leaf_Item(s, ptr);
	if (ptr->parent == nullptr)
	{
		return MakeRoot(kx, ptr, s);
	}
	BNode* pa = ptr->parent;
	int pos = pa->num;
	pa->key[0] = kx; //
	while (pos > 0 && kx  < pa->key[pos]) { --pos; }
	Insert_Brch_Item(pa, pos, kx, s);
	if (pa->num > BRCHMAX)
	{
		return Splice_Brch(pa);
	}
	else
	{
		return nullptr;
	}
}
bool Insert(BTree& tree, KeyType kx, Record* rec)
{
	if (tree.root == nullptr)
	{
		BNode* s = BuyLeaf();
		s->key[0] = kx;
		s->recptr[0] = rec;
		s->num = 1;
		tree.root = tree.first = s;
		return true;
	}
	Result resr = FindRoot(tree.root, kx);
	Result resf = FindLeaf(tree.first, kx);
	if (resf.pnode == nullptr)
	{
		cout << "Btree struct error " << endl;
		return false;
	}
	if (resf.tag)
	{
		cout << " xxx " << endl;
		return false;
	}
	BNode *ptr = resf.pnode;
	int pos = resf.index;
	Insert_Leaf_Item(ptr, pos, kx, rec);
	if (ptr->num > LEAFMAX)
	{
		BNode* newroot = Splice_Leaf(ptr);
		if (newroot != nullptr)
		{
			tree.root = newroot;
		}
	}
	return true;

}
int main()
{
	int ar[] = { 23,33,12,10,48,50 };
	int n = sizeof(ar) / sizeof(ar[0]);
	BTree myt;
	Init_BTree(myt);
	int i = 0;
	while (i < n)
	{
		Insert(myt, ar[i], nullptr);
		++i;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值