b树

B树详解与实现
/*
b 树
B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。

一颗m阶的B树定义如下:

1)每个结点最多有m-1个关键字。

2)根结点最少可以只有1个关键字。

3)非根结点至少有Math.ceil(m/2)-1个关键字。

4)每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。

5)所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。

//说明
5阶b树  最多有5个有效的孩子节点 4个关键字
最少有 ceil(5/2) - 1 = 2个关键字
节点个数并没有限制 只要叶子节点在同一层
*/

template<typename T>
struct BTreeNode
{
	BTreeNode()
	{
		m_data.clear();
		m_list.clear();
	}
	vector<T>			m_data;
	vector<BTreeNode *>	m_list;
};

template<typename T>
class BTree
{
public:
	BTree(int stage) :m_root(new BTreeNode<T>()), m_stage(stage), m_minPoint(static_cast<int>(ceil(stage / 2.0))), m_minKey(m_minPoint - 1){
		//二叉树 就不要搞过来了
		if (stage < 3)
		{
			m_stage = 2;
			m_minPoint = 1;
			m_minKey = 1;
		}
	}

	void Insert(T value);
	void CheckNode(BTreeNode<T> *node);

	void Delete(T value);
	void Delete_ex(BTreeNode<T> *	node,int value);

	void Print(BTreeNode<T> *	tRoot, int len);

public:
	BTreeNode<T> * m_root;
	int m_stage;
	int m_minPoint;
	int m_minKey;
};


template<typename T>
void BTree<T>::Insert(T value)
{
	BTreeNode<T> *first = m_root;
	vector<int>::iterator it;

	while (first)
	{
		it = upper_bound(first->m_data.begin(), first->m_data.end(), value);
		int index = it - first->m_data.begin();

		if (first->m_list.begin() + index  == first->m_list.end() || first->m_list[index] == nullptr)
		{
			first->m_data.insert(it, value);
			first->m_list.insert(first->m_list.begin() + index, nullptr);
			break;
		}
		else{
			first = first->m_list[index];
		}
	}
	CheckNode(first);
}

template<typename T>
void BTree<T>::CheckNode(BTreeNode<T> *node)
{
	if (node == nullptr) return;

	//需要分裂
	if (node->m_data.size() >= m_stage)
	{

		int mid = node->m_data.size()/2;

		BTreeNode<T> *temp1 = new BTreeNode<T>();
		BTreeNode<T> *temp2 = new BTreeNode<T>();

		temp1->m_data.insert(temp1->m_data.end(),node->m_data.begin(), node->m_data.begin() + mid);
		temp1->m_list.insert(temp1->m_list.end(),node->m_list.begin(), node->m_list.begin() + mid+1);

		temp2->m_data.insert(temp2->m_data.end(), node->m_data.begin() + mid + 1, node->m_data.end());
		temp2->m_list.insert(temp2->m_list.end(), node->m_list.begin() + mid + 1, node->m_list.end());


		T t = node->m_data[mid];

		if (node == m_root)
		{
			node->m_data.clear();
			node->m_data.push_back(t);

			node->m_list.clear();
			node->m_list.push_back(temp1);
			node->m_list.push_back(temp2);
		}
		else{
			//找父节点
			BTreeNode<T> *father = m_root;
			while (father)
			{
				if (find(father->m_list.begin(), father->m_list.end(), node) != father->m_list.end())
					break;
				auto it = upper_bound(father->m_data.begin(), father->m_data.end(), t);
				int index = it - father->m_data.begin();
				father = father->m_list[index];
			}
			auto it = find(father->m_list.begin(), father->m_list.end(), node);
			int index = it - father->m_list.begin();
			(*it) = temp2;

			father->m_data.insert(father->m_data.begin() + index, t);
			father->m_list.insert(father->m_list.begin() + index, temp1);

			CheckNode(father);
		}
	}
}

template<typename T>
void BTree<T>::Delete(T value)
{
	BTreeNode<T> *first = m_root;
	vector<int>::iterator it;
	while (first)
	{
		it = upper_bound(first->m_data.begin(), first->m_data.end(), value, less_equal<>());
		if (it != first->m_data.end() && (*it) == value)
		{
			break;
		}
		else{
			int index = it - first->m_data.begin();
			first = first->m_list[index];
		}
	}
	if (first == nullptr) return;

	//非叶子节点转化为叶子节点
	if (find_if(first->m_list.begin(), first->m_list.end(), bind2nd(not_equal_to<BTreeNode<T> *>(), nullptr)) != first->m_list.end())
	{
		BTreeNode<T> *next = first;
		int index = it - first->m_data.begin();
		for (int i = index; i >= 0; i--)
		{
			if (next->m_list[i] != nullptr)
			{
				next = next->m_list[i];
				break;
			}
		}
		if (first == next)
		{
			cout << "非叶子节点转化为叶子节点 Error" << endl;
			return;
		}
		while (next)
		{
			auto tem = find_if(next->m_list.rbegin(), next->m_list.rend(), bind2nd(not_equal_to<BTreeNode<T> *>(), nullptr));
			if (tem != next->m_list.rend())
			{
				next = (*tem);
			}
			else
				break;
		}

		if (next == nullptr)
		{
			cout << "非叶子节点转化为叶子节点 Error 2" << endl;
			return;
		}
		swap((*it), next->m_data.back());
		first = next;
		it = next->m_data.end() - 1;
	}
	int ttt = it - first->m_data.begin();
	first->m_data.erase(it);
	first->m_list.erase(first->m_list.begin() + ttt);

	Delete_ex(first,value);
}

template <typename T>
void BTree<T>::Delete_ex(BTreeNode<T> *	first,int value)
{
	if (first == nullptr) return;

	if (first->m_data.size() >= m_minKey)
	{
		
	}
	else{
		//找父节点
		BTreeNode<T> *father = nullptr;
		int index = -1;
		if (first != m_root)
		{
			if (first->m_data.size() > 0)
			{
				father = m_root;
				value = first->m_data[0];
				while (father)
				{
					if (find(father->m_list.begin(), father->m_list.end(), first) != father->m_list.end())
						break;
					auto fait = upper_bound(father->m_data.begin(), father->m_data.end(), value, less_equal<>());
					int index = fait - father->m_data.begin();
					father = father->m_list[index];
				}
			}
			else{
				//至少要5阶以上才不会走这里 5阶至少有2个数据节点
				deque<BTreeNode<T> *> templist = { m_root };
				BTreeNode<T> *findFather = nullptr;
				while (templist.size() > 0)
				{
					int len = templist.size();
					for (int i = 0; i < len; i++)
					{
						findFather = templist.front(); templist.pop_front();
						if (find(findFather->m_list.begin(), findFather->m_list.end(), first) != findFather->m_list.end())
						{
							father = findFather;
							break;
						}
							
						//第一个大于value的位置
						auto fait = upper_bound(findFather->m_data.begin(), findFather->m_data.end(), value, less_equal<>());
						int index = fait - findFather->m_data.begin();
						if (index - 1 >= 0 && index - 1 < findFather->m_list.size())
						{
							if (findFather->m_list[index - 1])
							templist.push_back(findFather->m_list[index - 1]);
						}
						if (index < findFather->m_list.size())
						{
							if (findFather->m_list[index])
							templist.push_back(findFather->m_list[index]);
						}
					}
				}
			}
		}
		
		if (father == nullptr)
		{
			int nCount = first->m_data.size();
			for (int i = 0; i < first->m_list.size(); i++)
			{
				if (first->m_list[i] != nullptr)
				{
					nCount += first->m_list[i]->m_data.size();
				}
			}
			if (nCount < m_stage)
			{
				for (int i = 0; i < first->m_list.size(); i++)
				{
					if (first->m_list[i] != nullptr)
					{
						BTreeNode<T> *temp = first->m_list[i];
						first->m_data.insert(first->m_data.begin() + i, temp->m_data.begin(), temp->m_data.end()); 
					}
				}
				for (auto it = first->m_list.begin(); it != first->m_list.end(); )
				{
					if ((*it) != nullptr)
					{
						BTreeNode<T> *temp = (*it);
						it = first->m_list.erase(it);
						it = first->m_list.insert(it, temp->m_list.begin(), temp->m_list.end());
						it += temp->m_list.size();
						delete temp;
						temp = nullptr;
					}
					else
						it++;
				}
			}
			return;
		}
		index = find(father->m_list.begin(), father->m_list.end(), first) - father->m_list.begin();

		BTreeNode<T> *left = nullptr, *right = nullptr;
		//左兄弟
		if (index - 1 >= 0)
		{
			left = father->m_list[index - 1];
			if (left != nullptr)
			{
				if (left->m_data.size() > m_minKey)
				{
					first->m_data.insert(first->m_data.begin(), father->m_data[index - 1]);
					first->m_list.insert(first->m_list.begin(), left->m_list.back());

					father->m_data[index - 1] = left->m_data.back();
					left->m_data.pop_back();
					left->m_list.pop_back();
					return;
				}
			}
		}
		//右兄弟
		if (index + 1 < father->m_list.size())
		{
			right = father->m_list[index + 1];
			if (right)
			{
				if (right->m_data.size() > m_minKey)
				{
					first->m_data.push_back( father->m_data[index]);
					first->m_list.push_back(right->m_list.front());

					father->m_data[index] = right->m_data.front();

					right->m_data.erase(right->m_data.begin());
					right->m_list.erase(right->m_list.begin());

					return;
				}
			}
		}
		//都没的借 合并
		if (left)
		{
			value = father->m_data[index - 1];
			first->m_data.insert(first->m_data.begin(), father->m_data[index - 1]);
			first->m_data.insert(first->m_data.begin(), left->m_data.begin(), left->m_data.end());
			first->m_list.insert(first->m_list.begin(), left->m_list.begin(), left->m_list.end());

			father->m_data.erase(father->m_data.begin() + index - 1);
			father->m_list.erase(father->m_list.begin() + index - 1);

			//if (first->m_list.size() > first->m_data.size() + 1 && first->m_list.back() == nullptr) first->m_list.pop_back();
		}
		else if (right)
		{
			value = father->m_data[index];
			right->m_data.insert(right->m_data.begin(), father->m_data[index]);
			right->m_data.insert(right->m_data.begin(), first->m_data.begin(), first->m_data.end());
			right->m_list.insert(right->m_list.begin(), first->m_list.begin(), first->m_list.end());

			//if (right->m_list.size() > right->m_data.size() + 1 && right->m_list.back() == nullptr) right->m_list.pop_back();

			father->m_data.erase(father->m_data.begin() + index);
			father->m_list.erase(father->m_list.begin() + index);

		}
		else{

		}
		Delete_ex(father,value);
	}

}
template <typename T>
void BTree<T>::Print(BTreeNode<T> *	tRoot, int len)
{
	if (tRoot == nullptr)
		return;
	
	int t = -1;
	if (tRoot != m_root && tRoot->m_data.size() == 0 && tRoot->m_list.size() <= 1)
	{
		cout << "xxx" << endl;
	}
	for (int i = 0; i < tRoot->m_data.size(); i++)
	{
		Print(tRoot->m_list[i], len + 1);
		cout << tRoot->m_data[i] << " ";
		t = i+1;
	}
	if (t > 0 && tRoot->m_list.size() > t)
			Print(tRoot->m_list[t], len + 1);
}

int Rand(int a)
{
	return rand() % a;
}
int main()
{
	int a[200];
	int b[21] = { 0, 7, 1, 17, 16, 19, 15, 2, 9, 6, 3, 12, 14, 5, 13, 11, 10, 8, 4, 18 };
	int c[21] = { 0, 9, 5, 10, 8, 14, 6, 15, 11, 3, 16, 18, 4, 7, 17, 13, 12, 1, 19, 2};
	srand(time(nullptr));
	int nCount = 10000,nStart = 2,nEnd = 50;
	while (nStart <= nEnd)
	{
		nCount = 100;
		while (nCount--)
		{
			BTree<int> t(nStart);
			for (int i = 1; i < 100; i++)
			{
				a[i] = i;
			}
			random_shuffle(a + 1, a + 100, Rand);
			
			for (int i = 1; i < 100; i++)
			{
				t.Insert(a[i]);
			}
			for (int i = 1; i < 100; i++)
				cout << a[i] << ",";
			cout << endl << endl;

			t.Print(t.m_root, 5);
			cout << endl;

			random_shuffle(a + 1, a + 100, Rand);

			for (int i = 1; i < 100; i++)
				cout << a[i] << ",";
			cout << endl << endl;
			for (int i = 1; i < 100; i++)
			{
				t.Delete(a[i]);
				t.Print(t.m_root, 5);
				cout << endl;
			}

			t.Print(t.m_root, 5);
			cout << endl;
			cout << nCount << endl;
		}
		++nStart;
	}
	
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值