B_树的插入

一.  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_树的插入》《B_树的插入》《B_树的插入》《B_树的插入》

三.  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;
}

 

    原文作者:B树
    原文地址: https://blog.csdn.net/qq_37954088/article/details/79629121
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞