B树插入删除c++完整实现

B树c++实现

第一次实现这么长的代码,从两个地方看的,看了蛮久了,都快背下来了-_-||,记录一下,有点乱
1.插入操作是在这看的,代码基本一样的,作者叫caleblbaker,github上找的,github上还有别人的,但是有些太高级了,我还不会(这里面也有删除但是我没看懂)https://github.com/CalebLBaker/b-tree
2. 删除是在这看的,好像是印度人的网站,代码基本一样的(这里面也有插入)https://www.geeksforgeeks.org/delete-operation-in-b-tree/
找了有些别的地方的代码好像有错误,所以找了这两个地方对照着看,有翻译软件可以不用看英语啦,哈哈

//btree.h
#include<iostream>

template <typename T>
struct BNode//一个节点中包含4个数据
{
	T* key;
	BNode<T>** child;
	int size;//当前节点中key的数量
	bool leaf;//是否为叶结点
};

template <typename T>
class BTree
{
	BNode<T>* root;//根节点
	int mindegeree;//一个节点中key和child的数量,key的数量最多为2*mindegeree-1,最少为mindegeree-1
	//child的数量比key多1
	void initializeNode(BNode<T>*&);//因为要初始化root,所以用引用,不然就初始化root的拷贝了
	void freeNode(BNode<T>*);//释放所有节点
	void traverse(BNode<T>*);//遍历输出
	void nodeInsert(BNode<T>*, T);//在一个节点中插入,不移动节点
	int findIndex(BNode<T>*, T);//返回一个节点中大于等于T的索引
	void splitchild(BNode<T>*, int);//当插入路径的节点的size满的话就分裂成两个
	T getpred(BNode<T>*, int);//得到比这个节点的值小的最大值(前继)
	T getsucc(BNode<T>*, int);//得到比这个节点的值大的最小值(后继)
	void removefromleaf(BNode<T>*, int);//从叶结点删除
	void removefromnonleaf(BNode<T>* , int);//从非叶结点删除
	void borrowfromleft(BNode<T>*, int);//左兄弟节点的大小size大于等于mindegree时,借用左兄弟的值
	void borrowfromright(BNode<T>*, int);//右兄弟节点的大小size大于等于mindegree时,借用右兄弟的值
	void merge(BNode<T>*, int);//当左右兄弟节点的大小size都小于mindegeree时,合并左兄弟或者右兄弟
	void fill(BNode<T>*, int);//保证删除时,其删除路径的大小size要大于等于mindegree
	void insert(BNode<T>*&, T);
	//插入操作,插入时采取主动分裂的方法,如果路径上的节点的size满的话,
	//就主动分裂(也可以和remove一样再加两个函数,移动多余的key到兄弟节点中,我当时没想到),
	//再将节点往下迭代,就能防止树一直往上分裂了。要更新root,所以要用引用。
	void remove(BNode<T>*&, T);
	//删除操作,删除时采取主动补齐的方法,如果路径上的节点的size小于mindegeree的话,就将节点的size补齐,
	//要么borrowfromleft要么borrowfromright,要么merge树的根的大小为0时,更新root为其child,所以要用引用

public:
	BTree(int i);
	~BTree<T>();

	void insert(T k)
	{
		insert(root, k);
	}

	void remove(T k)
	{
		remove(root, k);
	}

	void traverse()
	{
		traverse(root);
	}

};

template <typename T>
BTree<T>::BTree(int i):mindegeree(i),root(nullptr)
{
	initializeNode(root);
	root->leaf = true;
}
template <typename T>
BTree<T>::~BTree<T>()
{
	freeNode(root);
}
template<typename T>
void BTree<T>::initializeNode(BNode<T>*& curr)
{
	curr = new BNode<T>();//引用的用处,初始化根节点
	curr->key = new T[2 * mindegeree - 1];
	curr->child = new BNode<T> * [2 * mindegeree];
	curr->size = 0;
}
template<typename T>
void BTree<T>::freeNode(BNode<T>* root)
{
	if (!root->leaf)
		for (int i = 0; i <= root->size; ++i)
		{
			freeNode(root->child[i]);
		}
	delete[] root->key;
	delete[] root->child;
	delete root;
}
template<typename T>
void BTree<T>::traverse(BNode<T>* root)
{
	if (root->leaf)
		for (int i = 0; i < root->size; ++i)
			std::cout << root->key[i] << " ";
	else
		for (int i = 0; i <= root->size; ++i)
		{
			traverse(root->child[i]);
			if (i != root->size)
				std::cout << root->key[i] << " ";
		}
}
template<typename T>
void BTree<T>::nodeInsert(BNode<T>* curr, T k)
{
	int index = findIndex(curr, k);
	if (k == curr->key[index])
		return;
	for (unsigned i = curr->size; i >= index+1; --i)
	{
		curr->key[i] = curr->key[i-1];
		if (!curr->leaf)
			curr->child[i + 1] = curr->child[i];
	}
	curr->key[index] = k;
	++curr->size;
}
template<typename T>
int BTree<T>::findIndex(BNode<T>* curr, T k)
{
	int i = 0;
	for (; i < curr->size && k > curr->key[i]; ++i)
		;
	return i;
}
template<typename T>
void BTree<T>::splitchild(BNode<T>* parent, int i)
{
	BNode<T>* child = parent->child[i];
	BNode<T>* sibling = nullptr;
	initializeNode(sibling);
	sibling->leaf = child->leaf;
	for (int index = 0; index < mindegeree - 1; ++index)
	{
		sibling->key[index] = child->key[index + mindegeree];
		child->key[index + mindegeree] = 0;
		if (!child->leaf)
		{
			sibling->child[index] = child->child[index + mindegeree];
			child->child[index + mindegeree] = nullptr;
		}
	}
	if (!child->leaf)
	{
		sibling->child[mindegeree - 1] = child->child[2 * mindegeree - 1];
		child->child[2 * mindegeree - 1] = nullptr;
	}
	sibling->size += mindegeree - 1;
	child->size -= mindegeree - 1;
	nodeInsert(parent, child->key[mindegeree - 1]);
	parent->child[i + 1] = sibling;
	--child->size;
}
template<typename T>
void BTree<T>::insert(BNode<T>*& root, T k)//要用引用,不然更改不了root
{
	if (root->size == 2 * mindegeree - 1)
	{
		BNode<T>* newRoot = nullptr;
		initializeNode(newRoot);
		newRoot->leaf = false;
		newRoot->child[0] = root;
		root = newRoot;//引用的用处
		splitchild(newRoot, 0);
	}
	BNode<T>* curr = root;
	while (!curr->leaf)
	{
		int i = findIndex(curr, k);
		if (k == curr->key[i])
			return;
		else
			if (curr->child[i]->size == 2 * mindegeree - 1)
			{
				splitchild(curr, i);
				if (k > curr->child[i]->key[mindegeree - 1])
					++i;
			}
				
		curr = curr->child[i];
	}
	nodeInsert(curr, k);
}
template<typename T>
T BTree<T>::getpred(BNode<T>* root, int i)
{
	BNode<T>* curr = root->child[i];
	while (!curr->leaf)
		curr = curr->child[curr->size];
	return curr->key[curr->size - 1];
}
template<typename T>
T BTree<T>::getsucc(BNode<T>* root, int i)
{
	BNode<T>* curr = root->child[i + 1];
	while (!curr->leaf)
		curr = curr->child[0];
	return curr->key[0];
}
template<typename T>
void BTree<T>::merge(BNode<T>* curr, int i)
{
	BNode<T>* child = curr->child[i];
	BNode<T>* sibling = curr->child[i + 1];
	child->key[child->size] = curr->key[i];
	if (!child->leaf)
	{
		child->child[child->size + 1] = sibling->child[0];
		sibling->child[0] = nullptr;
	}
	++child->size;
	for (int ci = child->size, si = 0; si < sibling->size; ++ci, ++si)
	{
		child->key[ci] = sibling->key[si];
		sibling->key[si] = 0;
		if (!child->leaf)
		{
			child->child[ci + 1] = sibling->child[si+1];
			sibling->child[si+1] = nullptr;
		}
	}
	child->size += sibling->size;

	delete[] sibling->key;
	delete[] sibling->child;
	delete sibling;

	while (i < curr->size-1)
	{
		curr->key[i] = curr->key[i + 1];
		if (!curr->leaf)
			curr->child[i + 1] = curr->child[i + 2];
		++i;
	}
	if(!curr->leaf)
		curr->child[curr->size] = nullptr;
	--curr->size;
}
template<typename T>
void BTree<T>::removefromleaf(BNode<T>* leaf, int i)
{
	while (i < leaf->size-1)
	{
		leaf->key[i] = leaf->key[i + 1];
		++i;
	}
	--leaf->size;
	if (leaf->size == 0)
	{
		delete[] leaf->key;
		delete[] leaf->child;
		delete leaf;
		leaf = nullptr;
	}
}
template<typename T>
void BTree<T>::removefromnonleaf(BNode<T>* curr, int i)
{
	T value = curr->key[i];
	if (curr->child[i]->size >= mindegeree)
	{
		T pred = getpred(curr, i);
		curr->key[i] = pred;
		remove(curr->child[i], pred);
	}

	else if (curr->child[i + 1]->size >= mindegeree)
	{
		T succ = getsucc(curr, i);
		curr->key[i] = succ;
		remove(curr->child[i + 1], succ);
	}

	else
	{
		merge(curr, i);
		if (curr->size == 0)
		{
			BNode<T>* p = curr;
			curr = curr->child[i];
			delete[] p->key;
			delete[] p->child;
			delete p;
			p = nullptr;
		}
		remove(curr, value);
	}
}
template<typename T>
void BTree<T>::borrowfromleft(BNode<T>* curr, int i)
{
	BNode<T>* child = curr->child[i];
	BNode<T>* leftsibling = curr->child[i - 1];
	for (int ci = child->size; ci > 0; --ci)
	{
		child->key[ci] = child->key[ci-1];
		if (!child->leaf)
			child->child[ci + 1] = child->child[ci];
	}
	if (!child->leaf)
		child->child[1] = child->child[0];
	child->key[0] = curr->key[i-1];
	int size = leftsibling->size;
	if (!child->leaf)
	{
		child->child[0] = leftsibling->child[size];
		leftsibling->child[size] = nullptr;
	}
	++child->size;
	curr->key[i-1] = leftsibling->key[size-1];
	leftsibling->key[size] = 0;
	--leftsibling->size;
}
template<typename T>
void BTree<T>::borrowfromright(BNode<T>* curr, int i)
{
	BNode<T>* child = curr->child[i];
	BNode<T>* rightsibling = curr->child[i + 1];
	child->key[child->size] = curr->key[i];
	if (!child->leaf)
		child->child[child->size + 1] = rightsibling->child[0];
	++child->size;
	curr->key[i] = rightsibling->key[0];
	for (int ri = 0; ri < rightsibling->size - 1; ++ri)
	{
		rightsibling->key[ri] = rightsibling->key[ri + 1];
		if (!child->leaf)
			rightsibling->child[ri] = rightsibling->child[ri + 1];
	}
	if (!child->leaf)
	{
		rightsibling->child[rightsibling->size - 1] = rightsibling->child[rightsibling->size];
		rightsibling->child[rightsibling->size];
	}
	--rightsibling->size;
}
template<typename T>
void BTree<T>::fill(BNode<T>* root, int i)
{
	if (i > 0 && root->child[i - 1]->size >= mindegeree)
		borrowfromleft(root, i);
	else if (i < root->size && root->child[i + 1]->size >= mindegeree)
		borrowfromright(root, i);
	else
	{
		if (i != root->size)
			merge(root, i);
		else
			merge(root, i - 1);
	}
}
template<typename T>
void BTree<T>::remove(BNode<T>*& root, T k)
{
	if (root->size == 0)
		root = root->child[0];//引用的用处,改变根节点
	BNode<T>* curr = root;
	int i = findIndex(root, k);
	if (i < root->size && k == root->key[i])
	{
		if (root->leaf)
			removefromleaf(root, i);
		else
			removefromnonleaf(root, i);
	}
	else
	{
		if (root->leaf)
		{
			std::cout << "dont exist" << std::endl;
			return;
		}
		bool flag = (i == root->size) ? true : false;
		if (root->child[i]->size < mindegeree)
		{
			fill(root, i);
		}
		if (flag && i > root->size)
		{
			remove(root->child[i - 1], k);
		}
		else
			remove(root->child[i], k);
	}
}
//btree.cpp
#include"btree.h"

int main()
{
	BTree<int> t(3);
	t.insert(5);
	t.insert(25);
	t.insert(45);
	t.insert(65);
	t.insert(85);
	t.insert(95);
	t.insert(10);
	t.insert(15);
	t.insert(20);
	t.insert(30);
	t.insert(50);
	t.insert(55);
	t.insert(60);
	t.insert(70);
	t.insert(22);
	t.insert(24);
	t.insert(26);
	t.insert(28);
	t.insert(32);
	t.insert(34);
	t.insert(23);
	t.insert(61);
	t.insert(62);
	t.insert(63);
	
	t.traverse();
	std::cout << std::endl;
	t.remove(15);
	t.remove(25);
	t.remove(45);
	t.remove(28);
	t.remove(25);
	t.remove(45);

	t.traverse();
	return 0;
}

测试的数据## 有人找到B+树的c++实现能告诉一下我吗?我没找到o(╥﹏╥)o

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值