1. 程式人生 > >B+樹(C++實現)

B+樹(C++實現)

#include "BPlus_tree.h"
#include <iostream>
#include <algorithm>
using namespace std;

CBPlusTree::CBPlusTree(){
	m_Root = NULL;
	m_DataHead = NULL;
}

CBPlusTree::~CBPlusTree(){
	clear();
}

bool CBPlusTree::insert(KeyType key, const DataType& data){
	// 是否已經存在
	if (search(key))
	{
		return false;
	}
	// 找到可以插入的葉子結點,否則建立新的葉子結點
	if(m_Root==NULL)  
	{
		m_Root = new CLeafNode();
		m_DataHead = (CLeafNode*)m_Root;
		m_MaxKey = key;
	}
	if (m_Root->getKeyNum()>=MAXNUM_KEY) // 根結點已滿,分裂
	{
		CInternalNode* newNode = new CInternalNode();  //建立新的根節點
		newNode->setChild(0, m_Root);
		m_Root->split(newNode, 0);    // 葉子結點分裂
		m_Root = newNode;  //更新根節點指標
	}
	if (key>m_MaxKey)  // 更新最大鍵值
	{
		m_MaxKey = key;
	}
	recursive_insert(m_Root, key, data);
	return true;
}

void CBPlusTree::recursive_insert(CNode* parentNode, KeyType key, const DataType& data)
{
	if (parentNode->getType()==LEAF)  // 葉子結點,直接插入
	{
		((CLeafNode*)parentNode)->insert(key, data);
	}
	else
	{
		// 找到子結點
		int keyIndex = parentNode->getKeyIndex(key);
		int childIndex= parentNode->getChildIndex(key, keyIndex); // 孩子結點指標索引
		CNode* childNode = ((CInternalNode*)parentNode)->getChild(childIndex);
		if (childNode->getKeyNum()>=MAXNUM_LEAF)  // 子結點已滿,需進行分裂
		{
			childNode->split(parentNode, childIndex);      
			if (parentNode->getKeyValue(childIndex)<=key)   // 確定目標子結點
			{
				childNode = ((CInternalNode*)parentNode)->getChild(childIndex+1);
			}
		}
		recursive_insert(childNode, key, data);
	}
}

void CBPlusTree::clear()
{
	if (m_Root!=NULL)
	{
		m_Root->clear();
		delete m_Root;
		m_Root = NULL;
		m_DataHead = NULL;
	}
}

bool CBPlusTree::search(KeyType key)
{
	return recursive_search(m_Root, key);
}

bool CBPlusTree::recursive_search(CNode *pNode, KeyType key)const
{
	if (pNode==NULL)  //檢測節點指標是否為空,或該節點是否為葉子節點
	{
		return false;
	}
	else
	{
		int keyIndex = pNode->getKeyIndex(key);
		int childIndex = pNode->getChildIndex(key, keyIndex); // 孩子結點指標索引
		if (keyIndex<pNode->getKeyNum() && key==pNode->getKeyValue(keyIndex))
		{
			return true;
		}
		else
		{
			if (pNode->getType()==LEAF)   //檢查該節點是否為葉子節點
			{
				return false;
			}
			else
			{
				return recursive_search(((CInternalNode*)pNode)->getChild(childIndex), key);
			}
		}
	}
}

void CBPlusTree::print()const
{
	printInConcavo(m_Root, 10);
}

void CBPlusTree::printInConcavo(CNode *pNode, int count) const{
	if (pNode!=NULL)
	{
		int i, j;
		for (i=0; i<pNode->getKeyNum(); ++i)
		{
			if (pNode->getType()!=LEAF)
			{
				printInConcavo(((CInternalNode*)pNode)->getChild(i), count-2);
			}
			for (j=count; j>=0; --j)
			{
				cout<<"-";
			}
			cout<<pNode->getKeyValue(i)<<endl;
		}
		if (pNode->getType()!=LEAF)
		{
			printInConcavo(((CInternalNode*)pNode)->getChild(i), count-2);
		}
	}
}

void CBPlusTree::printData()const
{
	CLeafNode* itr = m_DataHead;
	while(itr!=NULL)
	{
		for (int i=0; i<itr->getKeyNum(); ++i)
		{
			cout<<itr->getData(i)<<" ";
		}
		cout<<endl;
		itr = itr->getRightSibling();
	}
}

bool CBPlusTree::remove(KeyType key)
{
	if (!search(key))  //不存在
	{
		return false;
	}
	if (m_Root->getKeyNum()==1)//特殊情況處理
	{
		if (m_Root->getType()==LEAF)
		{
			clear();
			return true;
		}
		else
		{
			CNode *pChild1 = ((CInternalNode*)m_Root)->getChild(0);
			CNode *pChild2 = ((CInternalNode*)m_Root)->getChild(1);
			if (pChild1->getKeyNum()==MINNUM_KEY && pChild2->getKeyNum()==MINNUM_KEY)
			{
				pChild1->mergeChild(m_Root, pChild2, 0);
				delete m_Root;
				m_Root = pChild1;
			}
		}
	}
	recursive_remove(m_Root, key);
	return true;
}

// parentNode中包含的鍵值數>MINNUM_KEY
void CBPlusTree::recursive_remove(CNode* parentNode, KeyType key)
{
	int keyIndex = parentNode->getKeyIndex(key);
	int childIndex= parentNode->getChildIndex(key, keyIndex); // 孩子結點指標索引
	if (parentNode->getType()==LEAF)// 找到目標葉子節點
	{
		if (key==m_MaxKey&&keyIndex>0)
		{
			m_MaxKey = parentNode->getKeyValue(keyIndex-1);
		}
		parentNode->removeKey(keyIndex, childIndex);  // 直接刪除
		// 如果鍵值在內部結點中存在,也要相應的替換內部結點
		if (childIndex==0 && m_Root->getType()!=LEAF && parentNode!=m_DataHead)
		{
			changeKey(m_Root, key, parentNode->getKeyValue(0));
		}
	}
	else // 內結點
	{
		CNode *pChildNode = ((CInternalNode*)parentNode)->getChild(childIndex); //包含key的子樹根節點
		if (pChildNode->getKeyNum()==MINNUM_KEY)                       // 包含關鍵字達到下限值,進行相關操作
		{
			CNode *pLeft = childIndex>0 ? ((CInternalNode*)parentNode)->getChild(childIndex-1) : NULL;                       //左兄弟節點
			CNode *pRight = childIndex<parentNode->getKeyNum() ? ((CInternalNode*)parentNode)->getChild(childIndex+1) : NULL;//右兄弟節點
			// 先考慮從兄弟結點中借
			if (pLeft && pLeft->getKeyNum()>MINNUM_KEY)// 左兄弟結點可借
			{
				pChildNode->borrowFrom(pLeft, parentNode, childIndex-1, LEFT);
			}
			else if (pRight && pRight->getKeyNum()>MINNUM_KEY)//右兄弟結點可借
			{
				pChildNode->borrowFrom(pRight, parentNode, childIndex, RIGHT);
			}
			//左右兄弟節點都不可借,考慮合併
			else if (pLeft)                    //與左兄弟合併
			{
				pLeft->mergeChild(parentNode, pChildNode, childIndex-1);
				pChildNode = pLeft;
			}
			else if (pRight)                   //與右兄弟合併
			{
				pChildNode->mergeChild(parentNode, pRight, childIndex);
			}
		}
		recursive_remove(pChildNode, key);
	}
}

void CBPlusTree::changeKey(CNode *pNode, KeyType oldKey, KeyType newKey)
{
	if (pNode!=NULL && pNode->getType()!=LEAF)
	{
		int keyIndex = pNode->getKeyIndex(oldKey);
		if (keyIndex<pNode->getKeyNum() && oldKey==pNode->getKeyValue(keyIndex))  // 找到
		{
			pNode->setKeyValue(keyIndex, newKey);
		}
		else   // 繼續找
		{
			changeKey(((CInternalNode*)pNode)->getChild(keyIndex), oldKey, newKey);
		}
	}
}

bool CBPlusTree::update(KeyType oldKey, KeyType newKey)
{
	if (search(newKey)) // 檢查更新後的鍵是否已經存在
	{
		return false;
	}
	else
	{
		int dataValue;
		remove(oldKey, dataValue);
		if (dataValue==INVALID_INDEX)
		{
			return false;
		}
		else
		{
			return insert(newKey, dataValue);
		}
	}
}

void CBPlusTree::remove(KeyType key, DataType& dataValue)
{
	if (!search(key))  //不存在
	{
		dataValue = INVALID_INDEX;
		return;
	}
	if (m_Root->getKeyNum()==1)//特殊情況處理
	{
		if (m_Root->getType()==LEAF)
		{
			dataValue = ((CLeafNode*)m_Root)->getData(0);
			clear();
			return;
		}
		else
		{
			CNode *pChild1 = ((CInternalNode*)m_Root)->getChild(0);
			CNode *pChild2 = ((CInternalNode*)m_Root)->getChild(1);
			if (pChild1->getKeyNum()==MINNUM_KEY && pChild2->getKeyNum()==MINNUM_KEY)
			{
				pChild1->mergeChild(m_Root, pChild2, 0);
				delete m_Root;
				m_Root = pChild1;
			}
		}
	}
	recursive_remove(m_Root, key, dataValue);
}

void CBPlusTree::recursive_remove(CNode* parentNode, KeyType key, DataType& dataValue)
{
	int keyIndex = parentNode->getKeyIndex(key);
	int childIndex= parentNode->getChildIndex(key, keyIndex); // 孩子結點指標索引
	if (parentNode->getType()==LEAF)// 找到目標葉子節點
	{
		if (key==m_MaxKey&&keyIndex>0)
		{
			m_MaxKey = parentNode->getKeyValue(keyIndex-1);
		}
		dataValue = ((CLeafNode*)parentNode)->getData(keyIndex);
		parentNode->removeKey(keyIndex, childIndex);  // 直接刪除
		// 如果鍵值在內部結點中存在,也要相應的替換內部結點
		if (childIndex==0 && m_Root->getType()!=LEAF && parentNode!=m_DataHead)
		{
			changeKey(m_Root, key, parentNode->getKeyValue(0));
		}
	}
	else // 內結點
	{
		CNode *pChildNode = ((CInternalNode*)parentNode)->getChild(childIndex); //包含key的子樹根節點
		if (pChildNode->getKeyNum()==MINNUM_KEY)                       // 包含關鍵字達到下限值,進行相關操作
		{
			CNode *pLeft = childIndex>0 ? ((CInternalNode*)parentNode)->getChild(childIndex-1) : NULL;                       //左兄弟節點
			CNode *pRight = childIndex<parentNode->getKeyNum() ? ((CInternalNode*)parentNode)->getChild(childIndex+1) : NULL;//右兄弟節點
			// 先考慮從兄弟結點中借
			if (pLeft && pLeft->getKeyNum()>MINNUM_KEY)// 左兄弟結點可借
			{
				pChildNode->borrowFrom(pLeft, parentNode, childIndex-1, LEFT);
			}
			else if (pRight && pRight->getKeyNum()>MINNUM_KEY)//右兄弟結點可借
			{
				pChildNode->borrowFrom(pRight, parentNode, childIndex, RIGHT);
			}
			//左右兄弟節點都不可借,考慮合併
			else if (pLeft)                    //與左兄弟合併
			{
				pLeft->mergeChild(parentNode, pChildNode, childIndex-1);
				pChildNode = pLeft;
			}
			else if (pRight)                   //與右兄弟合併
			{
				pChildNode->mergeChild(parentNode, pRight, childIndex);
			}
		}
		recursive_remove(pChildNode, key, dataValue);
	}
}

vector<DataType> CBPlusTree::select(KeyType compareKey, int compareOpeartor)
{
	vector<DataType> results;
	if (m_Root!=NULL)
	{
		if (compareKey>m_MaxKey)   // 比較鍵值大於B+樹中最大的鍵值
		{
			if (compareOpeartor==LE || compareOpeartor==LT)
			{
				for(CLeafNode* itr = m_DataHead; itr!=NULL; itr= itr->getRightSibling())
				{
					for (int i=0; i<itr->getKeyNum(); ++i)
					{
						results.push_back(itr->getData(i));
					}
				}
			}
		}
		else if (compareKey<m_DataHead->getKeyValue(0))  // 比較鍵值小於B+樹中最小的鍵值
		{
			if (compareOpeartor==BE || compareOpeartor==BT)
			{
				for(CLeafNode* itr = m_DataHead; itr!=NULL; itr= itr->getRightSibling())
				{
					for (int i=0; i<itr->getKeyNum(); ++i)
					{
						results.push_back(itr->getData(i));
					}
				}
			}
		}
		else  // 比較鍵值在B+樹中
		{
			SelectResult result;
			search(compareKey, result);
			switch(compareOpeartor)
			{
			case LT:
			case LE:
				{
					CLeafNode* itr = m_DataHead;
					int i;
					while (itr!=result.targetNode)
					{
						for (i=0; i<itr->getKeyNum(); ++i)
						{
							results.push_back(itr->getData(i));
						}
						itr = itr->getRightSibling();
					}
					for (i=0; i<result.keyIndex; ++i)
					{
						results.push_back(itr->getData(i));
					}
					if (itr->getKeyValue(i)<compareKey || 
						(compareOpeartor==LE && compareKey==itr->getKeyValue(i)))
					{
						results.push_back(itr->getData(i));
					}
				}
				break;
			case EQ:
				{
					if (result.targetNode->getKeyValue(result.keyIndex)==compareKey)
					{
						results.push_back(result.targetNode->getData(result.keyIndex));
					}
				}
				break;
			case BE:
			case BT:
				{
					CLeafNode* itr = result.targetNode;
					if (compareKey<itr->getKeyValue(result.keyIndex) ||
						(compareOpeartor==BE && compareKey==itr->getKeyValue(result.keyIndex))
						)
					{
						results.push_back(itr->getData(result.keyIndex));
					}
					int i;
					for (i=result.keyIndex+1; i<itr->getKeyNum(); ++i)
					{
						results.push_back(itr->getData(i));
					}
					itr = itr->getRightSibling();
					while (itr!=NULL)
					{
						for (i=0; i<itr->getKeyNum(); ++i)
						{
							results.push_back(itr->getData(i));
						}
						itr = itr->getRightSibling();
					}
				}
				break;
			default:  // 範圍查詢
				break;
			}
		}
	}
	sort<vector<DataType>::iterator>(results.begin(), results.end());
	return results;
}

vector<DataType> CBPlusTree::select(KeyType smallKey, KeyType largeKey)
{
	vector<DataType> results;
	if (smallKey<=largeKey)
	{
		SelectResult start, end;
		search(smallKey, start);
		search(largeKey, end);
		CLeafNode* itr = start.targetNode;
		int i = start.keyIndex;
		if (itr->getKeyValue(i)<smallKey)
		{
			++i;
		}
		if (end.targetNode->getKeyValue(end.keyIndex)>largeKey)
		{
			--end.keyIndex;
		}
		while (itr!=end.targetNode)
		{
			for (; i<itr->getKeyNum(); ++i)
			{
				results.push_back(itr->getData(i));
			}
			itr = itr->getRightSibling();
			i = 0;
		}
		for (; i<=end.keyIndex; ++i)
		{
			results.push_back(itr->getData(i));
		}
	}
	sort<vector<DataType>::iterator>(results.begin(), results.end());
	return results;
}

void CBPlusTree::search(KeyType key, SelectResult& result)
{
	recursive_search(m_Root, key, result);
}

void CBPlusTree::recursive_search(CNode* pNode, KeyType key, SelectResult& result)
{
	int keyIndex = pNode->getKeyIndex(key);
	int childIndex = pNode->getChildIndex(key, keyIndex); // 孩子結點指標索引
	if (pNode->getType()==LEAF)
	{
		result.keyIndex = keyIndex;
		result.targetNode = (CLeafNode*)pNode;
		return;
	}
	else
	{
		return recursive_search(((CInternalNode*)pNode)->getChild(childIndex), key, result);
	}
}

望大家不吝指教!