B+树(C++实现)

定义:

一棵M(M>2)阶的B+树满足以下定义:

1.B+树中包含两种类型的结点:内结点和叶子结点。内结点存有关键字和孩子结点的指针,叶子结点存有关键字和数据;

2.每一个关键字都会在叶子结点中出现,叶子结点按照关键字的大小排序,叶子结点中会存有指向兄弟结点的指针;

3.一棵B+树一般存有两个指针:一个指向根结点,一个指向存有最小关键字的叶子结点;

4.每个内结点至多有M个子树;

5.每个非根内结点至少有ceiling(M/2)个子树;

6.N个子树对应N-1个关键字(ps:另外一种说法是N个子树对应N个关键字,我参考的维基百科的定义http://en.wikipedia.org/wiki/B%2B_tree);

7.一个结点内关键字key1、key2、...、keyN,对应着N+1个孩子结点指针child1、child2、...、childN+1,且有child1<key1<child2<key2<...<keyN<childN+1;

8.叶子结点的关键字个数可以单独设置,一般和内结点关键字个数相同。

一图胜千言(图片来源:维基百科):

File:Bplustree.png

实现

  • BPlus_node.h
#ifndef BPLUS_NODE
#define BPLUS_NODE

#define NULL 0

enum NODE_TYPE{INTERNAL, LEAF};        // 结点类型:内结点、叶子结点
enum SIBLING_DIRECTION{LEFT, RIGHT};   // 兄弟结点方向:左兄弟结点、右兄弟结点
typedef float KeyType;                 // 键类型
typedef int DataType;                  // 值类型
const int ORDER = 7;                   // B+树的阶(非根内结点的最小子树个数)
const int MINNUM_KEY = ORDER-1;        // 最小键值个数
const int MAXNUM_KEY = 2*ORDER-1;      // 最大键值个数
const int MINNUM_CHILD = MINNUM_KEY+1; // 最小子树个数
const int MAXNUM_CHILD = MAXNUM_KEY+1; // 最大子树个数
const int MINNUM_LEAF = MINNUM_KEY;    // 最小叶子结点键值个数
const int MAXNUM_LEAF = MAXNUM_KEY;    // 最大叶子结点键值个数

// 结点基类
class CNode{
public:
	CNode();
	virtual ~CNode();

	NODE_TYPE getType() const {return m_Type;}
	void setType(NODE_TYPE type){m_Type = type;}
	int getKeyNum() const {return m_KeyNum;}
	void setKeyNum(int n){m_KeyNum = n;}
	KeyType getKeyValue(int i) const {return m_KeyValues[i];}
	void setKeyValue(int i, KeyType key){m_KeyValues[i] = key;}
	int getKeyIndex(KeyType key)const;  // 找到键值在结点中存储的下标
	// 纯虚函数,定义接口
	virtual void removeKey(int keyIndex, int childIndex)=0;  // 从结点中移除键值
	virtual void split(CNode* parentNode, int childIndex)=0; // 分裂结点
	virtual void mergeChild(CNode* parentNode, CNode* childNode, int keyIndex)=0;  // 合并结点
	virtual void clear()=0; // 清空结点,同时会清空结点所包含的子树结点
	virtual void borrowFrom(CNode* destNode, CNode* parentNode, int keyIndex, SIBLING_DIRECTION d)=0; // 从兄弟结点中借一个键值
	virtual int getChildIndex(KeyType key, int keyIndex)const=0;  // 根据键值获取孩子结点指针下标
protected:
	NODE_TYPE m_Type;
	int m_KeyNum;
	KeyType m_KeyValues[MAXNUM_KEY];
};

// 内结点
class CInternalNode : public CNode{
public:
	CInternalNode();
	virtual ~CInternalNode();

	CNode* getChild(int i) const {return m_Childs[i];}
	void setChild(int i, CNode* child){m_Childs[i] = child;}
	void insert(int keyIndex, int childIndex, KeyType key, CNode* childNode);
	virtual void split(CNode* parentNode, int childIndex);
	virtual void mergeChild(CNode* parentNode, CNode* childNode, int keyIndex);
	virtual void removeKey(int keyIndex, int childIndex);
	virtual void clear();
	virtual void borrowFrom(CNode* destNode, CNode* parentNode, int keyIndex, SIBLING_DIRECTION d);
	virtual int getChildIndex(KeyType key, int keyIndex)const;
private:
	CNode* m_Childs[MAXNUM_CHILD];
};

// 叶子结点
class CLeafNode : public CNode{
public:
	CLeafNode();
	virtual ~CLeafNode();

	CLeafNode* getLeftSibling() const {return m_LeftSibling;}
	void setLeftSibling(CLeafNode* node){m_LeftSibling = node;}
	CLeafNode* getRightSibling() const {return m_RightSibling;}
	void setRightSibling(CLeafNode* node){m_RightSibling = node;}
	DataType getData(int i) const {return m_Datas[i];}
	void setData(int i, const DataType& data){m_Datas[i] = data;}
	void insert(KeyType key, const DataType& data);
	virtual void split(CNode* parentNode, int childIndex);
	virtual void mergeChild(CNode* parentNode, CNode* childNode, int keyIndex);
	virtual void removeKey(int keyIndex, int childIndex);
	virtual void clear();
	virtual void borrowFrom(CNode* destNode, CNode* parentNode, int keyIndex, SIBLING_DIRECTION d);
	virtual int getChildIndex(KeyType key, int keyIndex)const;
private:
	CLeafNode* m_LeftSibling;
	CLeafNode* m_RightSibling;
	DataType m_Datas[MAXNUM_LEAF];
};
#endif
  • BPlus_node.cpp
#include "BPlus_node.h"

// CNode
CNode::CNode(){
	setType(LEAF);
	setKeyNum(0);
}

CNode::~CNode(){
	setKeyNum(0);
}

int CNode::getKeyIndex(KeyType key)const
{
	int left = 0;
	int right = getKeyNum()-1;
	int current;
	while(left!=right)
	{
		current = (left+right)/2;
		KeyType currentKey = getKeyValue(current);
		if (key>currentKey)
		{
			left = current+1;
		}
		else
		{
			right = current;
		}
	}
	return left;
}

// CInternalNode
CInternalNode::CInternalNode():CNode(){
	setType(INTERNAL);
}

CInternalNode::~CInternalNode(){
	
}

void CInternalNode::clear()
{
	for (int i=0; i<=m_KeyNum; ++i)
	{
		m_Childs[i]->clear();
		delete m_Childs[i];
		m_Childs[i] = NULL;
	}
}

void CInternalNode::split(CNode* parentNode, int childIndex)
{
	CInternalNode* newNode = new CInternalNode();//分裂后的右节点
	newNode->setKeyNum(MINNUM_KEY);
	int i;
	for (i=0; i<MINNUM_KEY; ++i)// 拷贝关键字的值
	{
		newNode->setKeyValue(i, m_KeyValues[i+MINNUM_CHILD]);
	}
	for (i=0; i<MINNUM_CHILD; ++i) // 拷贝孩子节点指针
	{
		newNode->setChild(i, m_Childs[i+MINNUM_CHILD]);
	}
	setKeyNum(MINNUM_KEY);  //更新左子树的关键字个数
	((CInternalNode*)parentNode)->insert(childIndex, childIndex+1, m_KeyValues[MINNUM_KEY], newNode);
}

void CInternalNode::insert(int keyIndex, int childIndex, KeyType key, CNode* childNode){
	int i;
	for (i=getKeyNum(); i>keyIndex; --i)//将父节点中的childIndex后的所有关键字的值和子树指针向后移一位
	{
		setChild(i+1,m_Childs[i]);
		setKeyValue(i,m_KeyValues[i-1]);
	}
	if (i==childIndex)
	{
		setChild(i+1, m_Childs[i]);
	}
	setChild(childIndex, childNode);
	setKeyValue(keyIndex, key);
	setKeyNum(m_KeyNum+1);
}

void CInternalNode::mergeChild(CNode* parentNode, CNode* childNode, int keyIndex)
{
	// 合并数据
	insert(MINNUM_KEY, MINNUM_KEY+1, parentNode->getKeyValue(keyIndex), ((CInternalNode*)childNode)->getChild(0));
	int i;
	for (i=1; i<=childNode->getKeyNum(); ++i)
	{
		insert(MINNUM_KEY+i, MINNUM_KEY+i+1, childNode->getKeyValue(i-1), ((CInternalNode*)childNode)->getChild(i));
	}
	//父节点删除index的key
	parentNode->removeKey(keyIndex, keyIndex+1);
	delete ((CInternalNode*)parentNode)->getChild(keyIndex+1);
}

void CInternalNode::removeKey(int keyIndex, int childIndex)
{
	for (int i=0; i<getKeyNum()-keyIndex-1; ++i)
	{
		setKeyValue(keyIndex+i, getKeyValue(keyIndex+i+1));
		setChild(childIndex+i, getChild(childIndex+i+1));
	}
	setKeyNum(getKeyNum()-1);
}

void CInternalNode::borrowFrom(CNode* siblingNode, CNode* parentNode, int keyIndex, SIBLING_DIRECTION d)
{
	switch(d)
	{
	case LEFT:  // 从左兄弟结点借
		{
			insert(0, 0, parentNode->getKeyValue(keyIndex), ((CInternalNode*)siblingNode)->getChild(siblingNode->getKeyNum()));
			parentNode->setKeyValue(keyIndex, siblingNode->getKeyValue(siblingNode->getKeyNum()-1));
			siblingNode->removeKey(siblingNode->getKeyNum()-1, siblingNode->getKeyNum());
		}
		break;
	case RIGHT:  // 从右兄弟结点借
		{
			insert(getKeyNum(), getKeyNum()+1, parentNode->getKeyValue(keyIndex), ((CInternalNode*)siblingNode)->getChild(0));
			parentNode->setKeyValue(keyIndex, siblingNode->getKeyValue(0));
			siblingNode->removeKey(0, 0);
		}
		break;
	default:
		break;
	}
}

int CInternalNode::getChildIndex(KeyType key, int keyIndex)const
{
	if (key==getKeyValue(keyIndex))
	{
		return keyIndex+1;
	}
	else
	{
		return keyIndex;
	}
}

// CLeafNode
CLeafNode::CLeafNode():CNode(){
	setType(LEAF);
	setLeftSibling(NULL);
	setRightSibling(NULL);
}

CLeafNode::~CLeafNode(){

}

void CLeafNode::clear()
{
	for (int i=0; i<m_KeyNum; ++i)
	{
		// if type of m_Datas is pointer
		//delete m_Datas[i];
		//m_Datas[i] = NULL;
	}
}

void CLeafNode::insert(KeyType key, const DataType& data)
{
	int i;
	for (i=m_KeyNum; i>=1 && m_KeyValues[i-1]>key; --i)
	{
		setKeyValue(i, m_KeyValues[i-1]);
		setData(i, m_Datas[i-1]);
	}
	setKeyValue(i, key);
	setData(i, data);
	setKeyNum(m_KeyNum+1);
}

void CLeafNode::split(CNode* parentNode, int childIndex)
{
	CLeafNode* newNode = new CLeafNode();//分裂后的右节点
	setKeyNum(MINNUM_LEAF);  
	newNode->setKeyNum(MINNUM_LEAF+1);
	newNode->setRightSibling(getRightSibling());
	setRightSibling(newNode);
	newNode->setLeftSibling(this);
	int i;
	for (i=0; i<MINNUM_LEAF+1; ++i)// 拷贝关键字的值
	{
		newNode->setKeyValue(i, m_KeyValues[i+MINNUM_LEAF]);
	}
	for (i=0; i<MINNUM_LEAF+1; ++i)// 拷贝数据
	{
		newNode->setData(i, m_Datas[i+MINNUM_LEAF]);
	}
	((CInternalNode*)parentNode)->insert(childIndex, childIndex+1, m_KeyValues[MINNUM_LEAF], newNode);
}

void CLeafNode::mergeChild(CNode* parentNode, CNode* childNode, int keyIndex)
{
	// 合并数据
	for (int i=0; i<childNode->getKeyNum(); ++i)
	{
		insert(childNode->getKeyValue(i), ((CLeafNode*)childNode)->getData(i));
	}
	setRightSibling(((CLeafNode*)childNode)->getRightSibling());
	//父节点删除index的key,
	parentNode->removeKey(keyIndex, keyIndex+1);
}

void CLeafNode::removeKey(int keyIndex, int childIndex)
{
	for (int i=keyIndex; i<getKeyNum()-1; ++i)
	{
		setKeyValue(i, getKeyValue(i+1));
		setData(i, getData(i+1));
	}
	setKeyNum(getKeyNum()-1);
}

void CLeafNode::borrowFrom(CNode* siblingNode, CNode* parentNode, int keyIndex, SIBLING_DIRECTION d)
{
	switch(d)
	{
	case LEFT:  // 从左兄弟结点借
		{
			insert(siblingNode->getKeyValue(siblingNode->getKeyNum()-1), ((CLeafNode*)siblingNode)->getData(siblingNode->getKeyNum()-1));
			siblingNode->removeKey(siblingNode->getKeyNum()-1, siblingNode->getKeyNum()-1);
			parentNode->setKeyValue(keyIndex, getKeyValue(0));			
		}
		break;
	case RIGHT:  // 从右兄弟结点借
		{
			insert(siblingNode->getKeyValue(0), ((CLeafNode*)siblingNode)->getData(0));
			siblingNode->removeKey(0, 0);
			parentNode->setKeyValue(keyIndex, siblingNode->getKeyValue(0));
		}
		break;
	default:
		break;
	}
}

int CLeafNode::getChildIndex(KeyType key, int keyIndex)const
{
	return keyIndex;
}
  • BPlus_tree.h
#ifndef BPLUS_TREE_H
#define BPLUS_TREE_H

#include "BPlus_node.h"
#include <vector>
using namespace std;

enum COMPARE_OPERATOR{LT, LE, EQ, BE, BT, BETWEEN}; // 比较操作符:<、<=、=、>=、>、<>
const int INVALID_INDEX = -1;

struct SelectResult
{
	int keyIndex;
	CLeafNode* targetNode;
};

class CBPlusTree{
public:
	CBPlusTree();
	~CBPlusTree();
	bool insert(KeyType key, const DataType& data);
	bool remove(KeyType key);
	bool update(KeyType oldKey, KeyType newKey);
	// 定值查询,compareOperator可以是LT(<)、LE(<=)、EQ(=)、BE(>=)、BT(>)
	vector<DataType> select(KeyType compareKey, int compareOpeartor);
	// 范围查询,BETWEEN
	vector<DataType> select(KeyType smallKey, KeyType largeKey);
	bool search(KeyType key); // 查找是否存在
	void clear();             // 清空
	void print()const;        // 打印树关键字
	void printData()const;    // 打印数据
private:
	void recursive_insert(CNode* parentNode, KeyType key, const DataType& data);
	void recursive_remove(CNode* parentNode, KeyType key);
	void printInConcavo(CNode *pNode, int count)const;
	bool recursive_search(CNode *pNode, KeyType key)const;
	void changeKey(CNode *pNode, KeyType oldKey, KeyType newKey);
	void search(KeyType key, SelectResult& result);
	void recursive_search(CNode* pNode, KeyType key, SelectResult& result);
	void remove(KeyType key, DataType& dataValue);
	void recursive_remove(CNode* parentNode, KeyType key, DataType& dataValue);
private:
	CNode* m_Root;
	CLeafNode* m_DataHead;
	KeyType m_MaxKey;  // B+树中的最大键
};

#endif
  • BPlus_tree.cpp
#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);
	}
}

望大家不吝指教!

转载于:https://www.cnblogs.com/newhand-liu/archive/2012/09/15/2793266.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值