B树详解

B树的引入

二叉搜索树、平衡二叉树、红黑树都是动态查找树,查找的时间复杂度和树的高度相关 O(log2n).
数据杂乱无章——线性搜索    O(n)
数字有序——二分查找  O(log2n)   最差退化成左单支树 O(n)
二叉搜索树/AVL/红黑树——O(log2n)
缺陷:数据量大时,树的高度太高,效率下降。


如何解决?
1.提高I/O的时间
2.降低树的高度——平衡多叉树。

B树定义

平衡的多叉树,称为B树(B-树)。

一棵M阶(M>2)的B树,是一个平衡的M路平衡搜索树,可以是空树或者满足以下性质:
1.根节点至少有两个孩子。
2.每个非根结点至少有M/2(上取整)个孩子,至多有M个孩子。
3.每个分根结点至少有M/2-1(上取整)个孩子,至多有M个孩子。
4.key[i]和key[i+1]之间的孩子结点的值介于key[i]、key[i+1]之间。
5.所有的叶子结点都在同一层。

图解

B树详解_第1张图片 B树详解_第2张图片

 B树详解_第3张图片B树详解_第4张图片

代码

#include 
using namespace std;

template
struct BTreeNode
{
	typedef BTreeNode Node;

	BTreeNode()
		:size(0)
		,_pParent(NULL)
	{}
	K _keys[M];  //关键字集合
	Node* _pSon[M+1];//孩子指针集合
	size_t size;
	Node* _pParent;
};

template
class BTree
{
	typedef BTreeNode Node;
public:
	BTree()
		:_pRoot(NULL)
	{}
bool Insert(const K&key)
{
	if (_pRoot == NULL)     //若树为空
	{
		_pRoot = new Node();
		_pRoot->_keys[0] = key;
		_pRoot->size++;
		_pRoot->_pSon[0] = NULL;
		_pRoot->_pSon[1] = NULL;
		return true;
	}

	//找插入位置
	pair s = Find(key);
	if (s.second != -1)   //已经存在
		return false;

	Node* pCur = s.first;
	Node* pSub = NULL;
	K key1 = key;
	while(true)
	{
		_Insertkey(pCur,key1,pSub);  //插入key值  pSub是插入的结点的孩子,若是新插入的,则pSub的值赋为NULL
                                              //若是往上调整的,则需要调整孩子

		if (pCur->size size/2;   //分裂取中 

			Node* pNew = new Node();
			size_t count = 0;
			size_t idx ;
			for( idx = mid+1;idxsize;)
			{
				pNew->_keys[count] = pCur->_keys[idx];
				pNew->_pSon[count++] = pCur->_pSon[idx++]; 
			}
			pNew->_pSon[count] = pCur->_pSon[idx];
			pCur->size = pCur->size - mid - 1;
			pNew->size = count;


			if (pCur == _pRoot)   //若原结点是根节点
			{
				_pRoot = new Node();
				_pRoot->_keys[0] = pCur->_keys[mid];
				_pRoot->_pSon[0] = pCur;
				pCur->_pParent = _pRoot;
				_pRoot->_pSon[1] = pNew;
				pNew->_pParent = _pRoot;
				_pRoot->size++;
				return true;
			} 

			pSub = pNew;    //更新孩子指针
			key1 = pCur->_keys[mid];   //更新要插入的值
			pCur = pCur->_pParent;  向上调整
		}
	}

}

pair Find(const K& key)   //若查找失败,则返回 NULL和-1 
{
	Node * pCur = _pRoot;
	Node* pParent = NULL;
	size_t idx = 0;
	while (pCur)
	{
		idx = 0;
		while (idx < pCur->size)
		{
			if (pCur->_keys[idx]_keys[idx]>key)
				break;
			else
				return make_pair(pCur,idx);
		}
		if (idx == pCur->size&&pCur->_pSon[idx] == NULL)
		{
			return make_pair(pCur,-1);
		}
		else
		{
			pParent = pCur;
			pCur = pCur->_pSon[idx];
		}
	}
	return make_pair(pParent,-1);
}
void InOrder()
{
	_InOrder(_pRoot);
}
private:
	void _InOrder(Node* &pRoot)
	{
		if (pRoot== NULL)
			return;

		size_t idx;
		for(idx =0 ;idxsize;++idx)
		{
			_InOrder(pRoot->_pSon[idx]);
			cout<_keys[idx]<<" ";
		}
		_InOrder(pRoot->_pSon[idx]);
	}
	void _Insertkey(Node* &pCur,const K& key,Node* pSub)
	{
		size_t end = pCur->size -1;
		while(end >= 0)
		{
			if (pCur->_keys[end] >key)    //后搬
			{

				pCur->_keys[end+1]= pCur->_keys[end];
				pCur->_pSon[end+2] = pCur->_pSon[end+1];
				--end;
			}
			else
			{
				pCur->_keys[end+1] = key;
				pCur->_pSon[end+2] = pSub;
				++pCur->size;
				return;
			}
		}
		pCur->_keys[0] = key;
		pCur->_pSon[0] = pSub;
		++pCur->size;
	}
private:
	Node* _pRoot;
};


你可能感兴趣的:(数据结构)