一. B_树的定义
一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树或者满足一下性质:
1. 根节点至少有两个孩子。
2. 每个非根节点至少有M/2(上取整)个孩子,至多有M 个孩子。
3. 每个非根节点至少有M/2-1( 上取整)个关键字,至多有M-1个关键字,并且以升序排列 。
4. ke y [i]和ke y[i+1]之间的孩子节点的值介于key[i ]、key[i+ 1]之间 。
5. 所有的叶子节点都在同一层。
二. B_树插入及其分裂
以序列{53 , 75 , 1 39 , 49, 14 5, 36, 1 01} 为例:
三. B_树插入的基本实现
#include<iostream>
using namespace std;
template<class K,int M>
struct BTreeNode
{
K _key[M];
BTreeNode<K, M>* _pSub[M + 1];
BTreeNode<K, M>* _Parent;
int _size;//关键字的个数
BTreeNode()
:_Parent(NULL)
, _size(0)
{
for (int i = 0; i < M + 1; i++)
{
_pSub[i] = NULL;
}
}
};
template<class K,int M>
class BTree
{
typedef BTreeNode<K, M> Node;
typedef Node* PNode;
public:
BTree()
:_pRoot(NULL)
{}
bool InsertNode( K&key, const int& M)
{
if (_pRoot == NULL)
{
_pRoot= new Node();
_pRoot->_key[0] = key;
_pRoot->_size++;
return true;
}
//找插入结点的位置
pair<PNode,int>ret = find(_pRoot,key, M);
if (ret.second >= 0)
{
return false;
}
PNode Pcur = ret.first;
PNode pSub = NULL;
while (true)
{
_InsertNode(Pcur, key, pSub);//插入结点
//判断是否需要分裂
if (Pcur->_size < M)
return true;
if (Pcur->_size >= M)
{
int mid = Pcur->_size >> 1;
PNode temp = new Node();
for (int i = mid + 1; i < Pcur->_size; i++)
{
temp->_key[temp->_size] = Pcur->_key[i];
temp->_pSub[temp->_size] = Pcur->_pSub[i];
if (temp->_pSub[temp->_size])
temp->_pSub[temp->_size]->_Parent = temp;
temp->_size++;
}
//孩子结点比关键字多搬移一个
temp->_pSub[temp->_size] = Pcur->_pSub[Pcur->_size];
if (temp->_pSub[temp->_size])
temp->_pSub[temp->_size]->_Parent = temp;
//更新Pcur的size
Pcur->_size -= (temp->_size + 1);
//如果当前结点为根节点,还要再处理
if (Pcur == _pRoot)
{
_pRoot = new Node;
_pRoot->_key[0] = Pcur->_key[mid];
_pRoot->_pSub[0] = Pcur;
_pRoot->_pSub[1] = temp;
temp->_Parent = _pRoot;
Pcur->_Parent = _pRoot;
_pRoot->_size++;
return true;
}
else
{
key = Pcur->_key[mid];
Pcur = Pcur->_Parent;
pSub = temp;
}
}
}
}
void InOrder()
{
_InOrder(_pRoot);
}
private:
void _InOrder(PNode PRoot)
{
PNode Pcur = PRoot;
if (PRoot == NULL)
return;
for (int i = 0; i < Pcur->_size; i++)
{
_InOrder(Pcur->_pSub[i]);
cout << Pcur->_key[i] << " ";
}
_InOrder(Pcur->_pSub[Pcur->_size]);
//cout << Pcur->_key[Pcur->_size] << " ";
}
//直接插入法
void _InsertNode(PNode pRoot, const K& key, PNode pSub)
{
PNode pCur = pRoot;
int sz = (pCur->_size )-1;
while( key < pCur->_key[sz] && sz>=0)
{
pCur->_key[sz + 1] = pCur->_key[sz];
pCur->_pSub[sz + 2] = pCur->_pSub[sz + 1];
sz--;
}
pCur->_key[sz + 1] = key;
pCur->_pSub[sz + 2] = pSub;
if (pSub)
pSub->_Parent = pCur;
pCur->_size++;
}
pair<PNode, int>find(PNode pRoot,const K& key, const int& M)
{
PNode pCur = pRoot;
int sz = pCur->_size;
PNode pParent = NULL;
while (pCur)
{
int i = 0;
for ( ; i < sz; )
{
if (pCur->_key[i] == key)
return pair<PNode, int>(pCur, i);
else if (pCur->_key[i]>key)
break;
else
i++;
}
pParent = pCur;
pCur = pCur->_pSub[i];
}
return pair<PNode, int>(pParent, -1);
}
private:
PNode _pRoot;
};
int main()
{
int arr[] = { 53, 75, 139, 49, 145, 36, 101 };
BTree<int, 3>bt;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
bt.InsertNode(arr[i],3);
bt.InOrder();
system("pause");
return 0;
}