B+樹(C++實現)
阿新 • • 發佈:2018-12-25
#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); } }
望大家不吝指教!