学习笔记:B+树模拟数据库索引查找

#include <iostream>
#include <queue>
using namespace std;

/******************************
PROGRAMER: Fanchenxin
M 阶B+树:
            (1) 非叶子节点key 个数和子树指针最大个数均为M.
            (2) 非叶子节点的key 为其子树节点M个key的最大或最小key.?
            (3) 叶子节点保存所有的key .
B+的特性:
            1.所有关键字都出现在叶子结点的链表中(稠密索引),
                且链表中的关键字恰好是有序的
            2.不可能在非叶子结点命中;       
            3.非叶子结点相当于是叶子结点的索引(稀疏索引),
                叶子结点相当于是存储(关键字)数据的数据层;       
            4.更适合文件索引系统


******************************/
/* 表结构 */
typedef struct _TableStruct_
{
    char name[20];  // 名字作为索引的关键字,经过某种运算成为一个整数关键字,假设名字没有重名的情况
    int age;
    char addr[256];
}TABLE_ST;


static TABLE_ST peopleInfoTable[20] = {
    {"杨洋", 20, "河北省秦皇岛市"},
    {"张占音", 21, "河南省许昌市"},
    {"沈东镇", 23, "黑龙江省讷河"},
    {"孟苏", 15, "河北省石家庄"},
    {"杨大勇", 20, "河北省唐山市"},
    {"李桂珍", 12, "上海市"},
    {"钱伟", 23, "福建省宁德"},
    {"蔡景观", 14, "陕西省宝鸡"},
    {"孙大宝", 35, "内蒙古包头"},
    {"赵国", 23, "四川省"},
    {"杨过", 21, "辽宁省大连市"},
    {"张勇", 21, "河南省许昌市"},
    {"沈陈东", 27, "江西省许昌市"},
    {"孟大海", 56, "海南"},
    {"杨治国", 34, "山东省"},
    {"李正", 14, "北京市"},
    {"钱爱装", 23, "山西省"},
    {"蔡大头", 14, "厦门市"},
    {"孙树", 35, "辽宁省沈阳市"},
    {"赵本山", 60, "辽宁省铁岭市"},
};  //人口信息表

#define M (4)

typedef struct _BPlusTreeNode_
{
    int keyNum;
    int key[M];
    bool isLeaf;
    struct _BPlusTreeNode_* subTree[M];
    struct _BPlusTreeNode_* father;
    //struct _BPlusTreeNode_* nextLeaf;  // 只有是叶子节点的时候才用到
    void* dataAddr[M];  //叶子节点指向的数据地址
}BPlusTreeNode;

BPlusTreeNode* newBPlusTreeNode(bool is_Leaf)
{
    BPlusTreeNode* newNode = (BPlusTreeNode*)malloc(sizeof(BPlusTreeNode));
    if(newNode != NULL)
    {
        newNode->keyNum = 0;
        memset(newNode->key, 0, (M) * sizeof(int));
        newNode->isLeaf = is_Leaf;
        memset(newNode->subTree, NULL, M * sizeof(BPlusTreeNode*));
        newNode->father = NULL;
        memset(newNode->dataAddr, NULL, M * sizeof(void*));
    }
    else
        return NULL;
    return newNode;
}


/* father为需要分裂的节点的父节点
    splitChildIdx 为需要分裂的节点的index, 
*/
void splitChild(BPlusTreeNode* father, int splitChildIdx, int key)
{
    if(!father)
        return;
    /*father->subTree[splitChildIdx] 为需要分裂的节点,分裂完后作为
        父节点subTree相应位置的左孩子*/
    BPlusTreeNode* leftChild = father->subTree[splitChildIdx];
    BPlusTreeNode* rightChild = newBPlusTreeNode(true); /* 新分裂出来的节点放在分裂点的右边 */
    rightChild->father = father;
    int i = 0, mid = M / 2;  // 左孩子mid个key, 右孩子 M-mid个key
    if(mid == 1){ // 为了保证至少有两个key
        mid++;
        if(leftChild->key[mid-1] > key)
            mid--;
    }
    
    for(; i < M-mid; i++)
    {
        rightChild->key[i] = leftChild->key[i+mid]; /* 将分裂节点的后M-mid个KEY给右孩子 */
    }
    memset(&leftChild->key[mid], 0, sizeof(int)*(M-mid)); /* 清空分裂节点后面的M-mid个KEY 值 */

    leftChild->keyNum = mid; 
    rightChild->keyNum = M-mid;

    /* 如果该分裂节点不是叶子节点,也就是说它存在子节点
        则需要将后面T个子节点送给右节点*/
    if(leftChild->isLeaf == false){
        rightChild->isLeaf = false;
        for(i = 0; i < M-mid; i++){
            rightChild->subTree[i] = leftChild->subTree[i+mid];
            rightChild->subTree[i]->father = rightChild;
        }
        /* 同时清除分裂节点的后面T个子节点指针 */
	 memset(&leftChild->subTree[mid], NULL, sizeof(BPlusTreeNode*) * (M-mid));
    }
    else{
        for(i = 0; i < M-mid; i++){
            rightChild->dataAddr[i] = leftChild->dataAddr[i+mid];
        }
        memset(&leftChild->dataAddr[mid], NULL, sizeof(void*)*(M-mid));
    }

    int j = father->keyNum;
    for(i = father->keyNum-1; i > splitChildIdx; i--){
        father->key[j] = father->key[i];
        father->subTree[j] = father->subTree[i];
        j--;
    }
    father->key[splitChildIdx] = leftChild->key[0]; /* 将分裂节点的中间KEY 放到父节点的KEY数组中 */
    father->key[splitChildIdx+1] =rightChild->key[0];
    father->subTree[splitChildIdx+1] = rightChild;
    if(father->keyNum == 0)
        father->keyNum += 2;
    else
        father->keyNum++;
    return;   
}

/* sm_key 是pNode 的subTree[index]节点的最小key */
void adjustKey(BPlusTreeNode* pNode, int sm_key, int index)
{
    if(!pNode)
        return;
    if(index != 0){
        pNode->key[index] = sm_key;
    }
    else{
        pNode->key[index] = sm_key;
        int i = 0;
        if(pNode->father != NULL){
            for(; i < pNode->father->keyNum; i++){
                if(pNode->father->subTree[i] == pNode)
                    break;
            }
            /* 继续向上调整最小key */
            adjustKey(pNode->father, sm_key, i);
        }
    }
}

/*往节点KEY个数未满的节点处插入key值*/
void insertKeyNotFull(BPlusTreeNode* pNode, int key, void* dataAddr)
{
    if(!pNode)
        return;

    int idx = pNode->keyNum - 1;
    if(pNode->isLeaf == true){
        if(pNode->keyNum == 0){
            pNode->key[0] = key;
            pNode->keyNum = 1;
            pNode->dataAddr[0] = dataAddr;
            return;
        }
 
        for(; idx >= 0; idx--)
        {
            if(key < pNode->key[idx]){
                pNode->key[idx+1] = pNode->key[idx];
                pNode->dataAddr[idx+1] = pNode->dataAddr[idx];
            }
            else
                break;
        }

	idx = idx + 1;

        if(idx == 0){ 
            pNode->key[0] = key;
            pNode->dataAddr[0] = dataAddr;
            if(pNode->father){
                int i = 0;
                for(; i < pNode->father->keyNum; i++){
                    if(pNode->father->subTree[i] == pNode)
                        break;
                }
                adjustKey(pNode->father, pNode->key[0], i);
            }
        }else{
            pNode->key[idx] = key;
            pNode->dataAddr[idx] = dataAddr;
        }
        pNode->keyNum++;
    }
    else{
        for(idx = pNode->keyNum-1; idx >= 0; idx--){
            if(key > pNode->key[idx])
                break;
        }

        if(idx < 0)
            idx = 0;
        
        pNode = pNode->subTree[idx];
     
        if(pNode->keyNum >= M){
            splitChild(pNode->father, idx, key);

            if(pNode->father->subTree[idx+1]->keyNum == 1 || 
                key > pNode->father->key[idx+1])
                pNode = pNode->father->subTree[idx+1];
        }
        
        insertKeyNotFull(pNode, key, dataAddr);
    }

    return;
}

void insertKey(BPlusTreeNode** root, int key, void* dataAddr)
{
    if(*root == NULL){
        *root = newBPlusTreeNode(true);
    }

    BPlusTreeNode* pCur = *root;    
    if(pCur->keyNum == M){
        BPlusTreeNode* newRoot = newBPlusTreeNode(false);
        newRoot->subTree[0] = *root;
        newRoot->subTree[0]->father = newRoot;
        *root = newRoot;

        splitChild(newRoot, 0, key);
        insertKeyNotFull(newRoot, key, dataAddr);
    }
    else{
        insertKeyNotFull(*root, key, dataAddr);
    }

    return;
}

void printKey(int* arry, int n, int layer)
{
    int i = 0;
	cout << "<" << layer << "> ";
    for(; i < n; i++)
        printf("%x  ", arry[i]);
}

static int layer = 1;

/* 深度优先遍历: layer 为该节点所在的层*/
void DPSearch(BPlusTreeNode* pNode)
{
    if(pNode == NULL)
        return;
    printKey(pNode->key, pNode->keyNum, layer);
    int i = 0; 
    layer++;
    for(; i < pNode->keyNum; i++){
		DPSearch(pNode->subTree[i]);
    }
    layer--;
    return;
}

/* 广度优先遍历 */
void BPSearch(BPlusTreeNode* pNode)
{
	if(pNode == NULL)
		return;
	
	queue<BPlusTreeNode*> q;
	q.push(pNode);
	BPlusTreeNode* pCur = NULL;
	while(!q.empty())
	{
		pCur = q.front();
		printKey(pCur->key, pCur->keyNum, 0);
		q.pop();
		int i = 0;
		for(; i < pCur->keyNum; i++){
			if(pCur->subTree[i]){
				q.push(pCur->subTree[i]);
			}
		}
	}
}

/* 姓名字符串转换为索引键值 */
int nameToKey(const char* name)
{
    int len = strlen(name);
    int key = 0, n = len-1;    
    for(; n >= 0; n--){
	int diff = 0;
	if(name[n] > '0')
		diff = name[n] - '0';
	else
		diff = '0' - name[n];
        key += diff;
    }
    return key / len;
}


BPlusTreeNode* searchKey(BPlusTreeNode* pCur, int key, int* keyIndex)
{
    if(pCur== NULL)
        return NULL;

    int i = 0; 
    if(pCur->isLeaf){

        for(i = 0; i < pCur->keyNum; i++){
            if(pCur->key[i] == key)
                break;
        }

        if(i >= pCur->keyNum)
            return NULL;
        *keyIndex = i;
        return pCur;
    }
    else{
        for(i = pCur->keyNum - 1; i >= 0; i--){
            if(key >= pCur->key[i])
                break;
        }

        if(i < 0){
            cout << "no match subTree, key = " << key << "; small key = " << pCur->key[0] << endl;
            return NULL;
        }

        return searchKey(pCur->subTree[i], key, keyIndex);
    }
}

void searchInfoByName(BPlusTreeNode* pRoot, const char* name)
{
    if(!pRoot || !name)
        return;
    int keyIndx = 0, key = 0;
    key = nameToKey(name);
    BPlusTreeNode* leaf = searchKey(pRoot, key, &keyIndx);
    if(leaf){
        cout << name << " 的索引key 值为: 0x" << hex << key << endl;
        TABLE_ST* personInfo = (TABLE_ST*)leaf->dataAddr[keyIndx];
        cout << "年龄: " << dec << personInfo->age << endl;
        cout << "家庭住址: " << personInfo->addr << endl;
    }
    else
        cout << "找不到" << name << " 的相关信息" << endl;

    return;
}


BPlusTreeNode* create_BPlusTree(const TABLE_ST* table, int rowNum)
{
    BPlusTreeNode* root = newBPlusTreeNode(true);
    //BPlusTreeNode* LeafHead = newBPlusTreeNode(true);
    //LeafHead->nextLeaf = root;
    if(root){
        int i = 0;
        for(; i < rowNum; i++){
            int key = nameToKey(table[i].name);
            insertKey(&root, key, (void*)&table[i]);
        }
    }
    return root;
}

/* pNode  需要删除的key 在该节点里
    isLeft标识找到的兄弟是左兄弟还是右兄弟 
    index 为pNode 在父节点的subTree数组中的位置
    返回值为true 表示找到否则没找到
    */
bool checkBrotherIsRich(BPlusTreeNode* pNode, int index, bool* isLeft) 
{
    if(pNode == NULL)
        return false;
    if(pNode->father == NULL)
        return false;
    BPlusTreeNode* father = pNode->father;

    if(index == 0) //如果该节点是最左边的孩子,则只存在右兄弟
    {
        if(father->subTree[index+1]->keyNum > 2){
            *isLeft = false;
            return true;
        }
        else
            return false;
    }

    if(index == father->keyNum-1) //如果该节点是最右边的孩子,则只存在左兄弟
    {
        if(father->subTree[index-1]->keyNum > 2){
            *isLeft = true;
            return true;
        }
        else
            return false;
    }

    /* 一般是先从左兄弟开始判断,移动左兄弟的key
        比较方便,不会产生最小key 变化的问题,不需要
        向上调整*/
    if(index > 0 && index < father->keyNum-1){
        if(father->subTree[index-1]->keyNum > 2){
            *isLeft = true;
            return true;
        }
        else{
            if(father->subTree[index+1]->keyNum > 2){
                *isLeft = false;
                return true;
            }
            else
                return false;
        }
    }

    return false;
}

/* 将arry 数组index 后面的内容前移一个单位到index 位置 */
template<typename T>
void moveProcess(T arry[], int index, int n)
{
    int i = index, j = index + 1;
    for(; j < n; j++){
        arry[i++] = arry[j];
    }
    arry[i] = 0;
}


/* 如果兄弟节点都不富裕,父节点执行合并或旋转操作
    sub_idx为需要合并或旋转操作的节点在pNode的subTree[]的index*/
void mergeOrRotate(BPlusTreeNode* pNode)
{
    if(!pNode)
        return;

    if(pNode->father == NULL){ // pNode 为根节点 且 keyNum == 1, 将根节点指针指向子节点
        BPlusTreeNode* child = pNode->subTree[0];
        /* 将子节点的所有拷贝给根节点 */
	 int i = 0;
	 for(; i < child->keyNum; i++){
	 	pNode->key[i] = child->key[i];
		if(child->isLeaf == false){
			pNode->subTree[i] = child->subTree[i];
			pNode->subTree[i]->father = pNode;
		}else{
			pNode->dataAddr[i] = child->dataAddr[i];
			pNode->subTree[i] = NULL;
		}
	 }
	 pNode->keyNum = child->keyNum;
	 free(child);
	 child = NULL;
        return;
    }

    BPlusTreeNode* pFather = pNode->father;
    int sub_idx = 0;
    for(; sub_idx < pFather->keyNum; sub_idx++){
        if(pFather->subTree[sub_idx] == pNode)
            break;
    }

    bool isLeft = false;
    if(checkBrotherIsRich(pNode, sub_idx, &isLeft)){
        if(isLeft){  // 如果左兄弟富裕 keyNum > 2
            /* 将左兄弟的最右的分支借过来(右旋操作) */
            BPlusTreeNode* pLeftBrother = pFather->subTree[sub_idx-1];
            int i = pNode->keyNum - 1;
            for(; i >= 0; i--){
                pNode->key[i+1] = pNode->key[i];
                pNode->subTree[i+1] = pNode->subTree[i];
                //pNode->dataAddr[i+1] = pNode->dataAddr[i];

            }
            int n = pLeftBrother->keyNum-1;
            pNode->key[0] = pLeftBrother->key[n];
            pNode->subTree[0] = pLeftBrother->subTree[n];
            pNode->subTree[0]->father = pNode;
            //pNode->dataAddr[0] = pLeftBrother->dataAddr[n];
            pLeftBrother->key[n] = 0;
            pLeftBrother->subTree[n] = NULL;
            //pLeftBrother->dataAddr[n] = NULL;
            pLeftBrother->keyNum--;
            pNode->keyNum++;
            adjustKey(pFather, pNode->key[0], sub_idx);
        }
        else{ // 如果右兄弟富裕 keyNum > 2
            BPlusTreeNode* pRightBrother = pFather->subTree[sub_idx+1];
            int n = pNode->keyNum;
            pNode->key[n] = pRightBrother->key[0];
            pNode->subTree[n] = pRightBrother->subTree[0];
            pNode->subTree[n]->father = pNode;
            //pNode->dataAddr[n] = pRightBrother->dataAddr[0];
            moveProcess(pRightBrother->key, 0, pRightBrother->keyNum);
            moveProcess(pRightBrother->subTree, 0, pRightBrother->keyNum);
            //moveProcess(pRightBrother->dataAddr, 0, pRightBrother->keyNum);
            pRightBrother->key[pRightBrother->keyNum-1] = 0;
            pRightBrother->subTree[pRightBrother->keyNum-1] = NULL;
            //pRightBrother->dataAddr[pRightBrother->keyNum-1] = NULL;
            pRightBrother->keyNum--;
            pNode->keyNum++;
            adjustKey(pFather, pRightBrother->key[0], sub_idx+1);
        }
    }
    else{ // 如果左右兄弟都不富裕
        /* 将其和左或右兄弟合并
             合并将保留左节点*/
        BPlusTreeNode* pLeft = NULL, *pRight = NULL;
        int keep_id = 0;
        if(sub_idx == 0){
            pLeft = pNode;
            pRight = pFather->subTree[sub_idx+1];
            keep_id = sub_idx;
        }
        else{
            pLeft = pFather->subTree[sub_idx-1];
            pRight = pNode;
            keep_id = sub_idx -1;
        }

        int n_l = pLeft->keyNum, n_r = pRight->keyNum;
        int i = n_l, j = 0;
        for(; j < n_r; j++){
            pLeft->key[i] = pRight->key[j];
            pLeft->subTree[i] = pRight->subTree[j];
            pLeft->subTree[i]->father = pLeft;
            i++;
        }
        pLeft->keyNum = i;

        moveProcess(pFather->key, keep_id+1, pFather->keyNum);
        moveProcess(pFather->subTree, keep_id+1, pFather->keyNum);
        pFather->keyNum--;

        free(pRight);
        pRight = NULL;
        
        /* 如果合并后父节点的keyNum < 2 则递归调用 */
        if(pFather->keyNum < 2){
            mergeOrRotate(pFather);
        }
    }
    
    return;
}


/* pNode 是叶子节点,sub_idx 为其在父节点subTree 中的索引 */
void leafMergeAndDelete(BPlusTreeNode* pNode, int sub_idx, int deleteKey)
{
    if(pNode == NULL)
        return;

    BPlusTreeNode* pFather = pNode->father;
    /* 先删除deleteKey */
    int oldSmKey = pNode->key[0];
    int i = 0, j = 0;
    for(; j < pNode->keyNum; j++){
        if(pNode->key[j] != deleteKey){
            pNode->key[i] = pNode->key[j];
            pNode->dataAddr[i] = pNode->dataAddr[j];
            i++;
        }
    }
    if(pNode->key[0] != oldSmKey){ //如果最小key 发生变化,调整最小key
        adjustKey(pFather, pNode->key[0], sub_idx);
    }
    pNode->keyNum--;
    
    /* 执行合并操作 */
    if(sub_idx == pFather->keyNum-1){ //如果是最右的孩子,就合并到左兄弟去
        BPlusTreeNode* pLeftBrother = pFather->subTree[sub_idx-1];
        int i = pLeftBrother->keyNum, j = 0;
        for(; j < pNode->keyNum; j++){
            pLeftBrother->key[i] = pNode->key[j];
            pLeftBrother->dataAddr[i] = pNode->dataAddr[j];
            i++;
        }
        pLeftBrother->keyNum = i;
        pFather->keyNum--;
        pFather->key[pFather->keyNum] = 0;
        pFather->subTree[pFather->keyNum] = NULL;

        free(pNode);
        pNode = NULL;
    }
    else{ // 把右兄弟合并过来比较方便,不用关心最小key的问题
        BPlusTreeNode* pRightBrother = pFather->subTree[sub_idx+1];
        int i = pNode->keyNum, j = 0;
        for(; j < pRightBrother->keyNum; j++){
            pNode->key[i] = pRightBrother->key[j];
            pNode->dataAddr[i] = pRightBrother->dataAddr[j];
            i++;
        }
        pNode->keyNum = i;

        /* father的sub_idx+1后的key 和subTree指针前移 */
        moveProcess(pFather->key, sub_idx+1, pFather->keyNum);
        moveProcess(pFather->subTree, sub_idx+1, pFather->keyNum);
        pFather->keyNum--;
        pFather->key[pFather->keyNum] = 0;
        pFather->subTree[pFather->keyNum] = NULL;

        free(pRightBrother);
        pRightBrother = NULL;
    }

    /* 合并完后判断父节点的key 个数 */
    if(pFather->keyNum < 2){  // case 2.2
        mergeOrRotate(pFather);
    }

    // case 2.1 合并后父节点的key个数任然>= 2则直接结束
    return;
}


/***************************************************************************
(1) 如果叶子节点的key 个数大于2,则直接删除即可。
(2) 如果不大于2个,则看看其左(右)兄弟(如果存在)是否富裕
            case 1: 如果富裕则借一个key, 再删除deleteKey.
            case 2: 如果兄弟节点都不富裕,则删除deleteKey 后将其和左(右)
                        节点进行合并
                  case 2.1: 如果合并后父节点任然富裕,则结束
                  case 2.2: 如果合并后父节点的key 个数小于2则递归往上继续
                                进行合并操作

*********************************************************************************/
void deleteKey(BPlusTreeNode* pCur, int deleteKey)
{
    if(!pCur)
        return;

    int sub_idx = 0;
    /* 一直找到叶子节点 */
    BPlusTreeNode* pDeleteLeaf = pCur;
    while(pDeleteLeaf->isLeaf == false)
    {
        for(sub_idx = pDeleteLeaf->keyNum - 1; sub_idx >= 0; sub_idx--){
            if(deleteKey >= pDeleteLeaf->key[sub_idx])
                break;
        }
        if(sub_idx < 0){
            cout << deleteKey << " 不存在" << endl;
            return;
        }
        pDeleteLeaf = pDeleteLeaf->subTree[sub_idx];
    }
    
    if(pDeleteLeaf->keyNum > 2){ /* 如果叶子节点的key 个数大于2 直接删除 */
        int i = 0, j = 0;
	 int oldSmKey = pDeleteLeaf->key[0];
        for(; i < pDeleteLeaf->keyNum; i++)
        {
            if(pDeleteLeaf->key[i] != deleteKey){
                pDeleteLeaf->key[j] = pDeleteLeaf->key[i];
                pDeleteLeaf->dataAddr[j] = pDeleteLeaf->dataAddr[i];
                j++;
            }
        }

	 if(j == pDeleteLeaf->keyNum){
	 	cout << deleteKey << " 未找到!!!!!" << endl;
		return;
	 }
        pDeleteLeaf->key[j] = 0;
        pDeleteLeaf->dataAddr[j] = NULL;
        pDeleteLeaf->keyNum--;
	 if(pDeleteLeaf->key[0] != oldSmKey)
	 	adjustKey(pDeleteLeaf->father, pDeleteLeaf->key[0], sub_idx);
    }
    else{
        BPlusTreeNode* pFather = pDeleteLeaf->father;
        bool isLeft = false;
        if(checkBrotherIsRich(pDeleteLeaf, sub_idx, &isLeft)){ // case 1 如果兄弟节点富裕 key > 2
            if(isLeft){  // 如果富裕的是左兄弟   
                BPlusTreeNode* pLeftBrother = pFather->subTree[sub_idx-1];
                int n = pLeftBrother->keyNum;
                int borrowKey = pLeftBrother->key[n-1];  //借用的key
                void* addrTmp = pLeftBrother->dataAddr[n-1];
                pFather->key[sub_idx] = borrowKey; // 因为是左兄弟,sub_idx不可能是0,所以没必要向上调整最小key
                pLeftBrother->key[n-1] = 0;
                pLeftBrother->dataAddr[n-1] = NULL;
                pLeftBrother->keyNum--;  //兄弟的key个数减一
                /* 删除deleteKey */
                int i = 1, j = 0;
                for(; j < pDeleteLeaf->keyNum; j++){
                    if(pDeleteLeaf->key[j] != deleteKey){
                        pDeleteLeaf->key[i] = pDeleteLeaf->key[j];
                        pDeleteLeaf->dataAddr[i] = pDeleteLeaf->dataAddr[j];
                        i++;
                    }
                }
                pDeleteLeaf->key[0] = borrowKey;
                pDeleteLeaf->dataAddr[0] = addrTmp;
            }else{  // 如果富裕的是右兄弟
                BPlusTreeNode* pRightBrother = pFather->subTree[sub_idx+1];
                int borrowKey = pRightBrother->key[0];  //借用的key
                void* addrTmp = pRightBrother->dataAddr[0];
                pFather->key[sub_idx+1] = pRightBrother->key[1]; 
                int oldSmKey = pDeleteLeaf->key[0];
                moveProcess(pRightBrother->key, 0, pRightBrother->keyNum);  //key 前移
                moveProcess(pRightBrother->dataAddr, 0, pRightBrother->keyNum);
                pRightBrother->keyNum--;  //兄弟的key个数减一
                /* 删除deleteKey */
                int i = 0, j = 0;
                for(; j < pDeleteLeaf->keyNum; j++){
                    if(pDeleteLeaf->key[j] != deleteKey){
                        pDeleteLeaf->key[i] = pDeleteLeaf->key[j];
                        pDeleteLeaf->dataAddr[i] = pDeleteLeaf->dataAddr[j];
                        i++;
                    }
                }
                pDeleteLeaf->key[i] = borrowKey;
                pDeleteLeaf->dataAddr[i] = addrTmp;
                
                if(pDeleteLeaf->key[0] != oldSmKey){ //如果最小key 发生变化,调整最小key
                    adjustKey(pFather, pDeleteLeaf->key[0], sub_idx);
                }
            }
        }
        else{  // case 2 如果兄弟节点不富裕 key <= 2
            leafMergeAndDelete(pDeleteLeaf, sub_idx, deleteKey);
        }
    }
    return;
}

int main()
{
    BPlusTreeNode* pRoot;
    pRoot = create_BPlusTree(peopleInfoTable, 20);
    /*
        M = 4 的B+树建完后是这样的:
                                       4f                              5f                    6c
                                      /                                 |                        \
                           4f      52     58      5b               5f        64                6c   70
                           /        |       |        \           /            \               /       \
                      4f 50 51    52 57   58 59    5b 5d      5f 63       64 66 69 6b       6c 6d  70 73 76
    */

    DPSearch(pRoot);
    cout << endl;

    searchInfoByName(pRoot, "沈东镇");
    searchInfoByName(pRoot, "杨大勇");
    searchInfoByName(pRoot, "李正");
    searchInfoByName(pRoot, "赵国");
    
    int key = nameToKey("沈东镇");
    cout << "删除key = 0x" << hex << key << endl;
    deleteKey(pRoot, key);
    DPSearch(pRoot);
    cout << endl;
    
    /*
        删除0x5f 后:
                                       4f                              63                    6c
                                      /                                 |                        \
                           4f      52     58      5b               63        66                6c   70
                           /        |       |        \           /            \               /       \
                      4f 50 51    52 57   58 59    5b 5d      63 64        66 69 6b         6c 6d  70 73 76
    */
    searchInfoByName(pRoot, "沈东镇");

    key = nameToKey("杨大勇");
    cout << "删除key = 0x" << hex << key << endl;
    deleteKey(pRoot, key);
    DPSearch(pRoot);
    cout << endl;
    
    /*
        删除0x5b 后:
                                       4f                              63                    6c
                                      /                                 |                        \
                           4f      52     58                      63        66               6c   70
                           /        |       |                    /            \              /       \
                      4f 50 51    52 57   58 59 5d            63 64         66 69 6b       6c 6d  70 73 76
    */

    deleteKey(pRoot, 0x52);
    cout << "删除key = 0x52" << endl;
    DPSearch(pRoot);
    cout << endl;


    /*
        删除0x52 后:
                                       4f                              63                    6c
                                      /                                 |                        \
                           4f      51     58                      63        66               6c   70
                           /        |       |                   /            \              /       \
                       4f  50     51 57   58 59 5d           63 64        66 69 6b        6c 6d  70 73 76
    */

    deleteKey(pRoot, 0x64);
    cout << "删除key = 0x64" << endl;
    DPSearch(pRoot);
    cout << endl;
    
    /*
        删除0x64 后:
                                   4f                              63                    6c
                                  /                                 |                        \
                       4f      51     58                      63        69                6c   70
                       /        |       |                    /            \              /       \
                   4f  50     51 57  58 59 5d             63 66          69 6b         6c 6d  70 73 76
 
    */

    deleteKey(pRoot, 0x63);
    cout << "删除key = 0x63" << endl;
    DPSearch(pRoot);
    cout << endl;
    
    /*
        删除0x63 后:
        (1) 合并:
                                    4f                  63               6c
                                  /                      |                  \
                       4f      51     58                66              6c   70
                       /        |       |               |              /       \
                   4f  50     51 57   58 59 5d       66 69 6b        6c 6d  70 73 76

        (2) 旋转:
                                4f                  58                  6c
                              /                      |                      \
                        4f      51              58       66               6c   70
                        /        \            /           \              /       \
                   4f  50      51 57     58 59 5d     66 69 6b        6c 6d  70 73 76

    */

	deleteKey(pRoot, 0x4f);
	cout << "删除key = 0x4f" << endl;
	DPSearch(pRoot);
	cout << endl;

    /*
        删除0x4f 后:
        (1) 合并:
					 4f 		       58 				     6c
				   /				   | 					 \
			     50 		         58	   66			    6c   70
			     |		  		   /		   \     	     /     \
		      50 51 57         58 59 5d	    66 69 6b       6c 6d  70 73 76

        (2) 合并:
                                    50                                  6c
                                    /                                     \
                        50       58       66                           6c   70
                        /         |          \                        /       \
                    50 51 57   58 59 5d    66 69 6b                 6c 6d  70 73 76

    */

	deleteKey(pRoot, 0x50);
	cout << "删除key = 0x50" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x50后:
                                    51                                  6c
                                    /                                     \
                        51       58       66                           6c   70
                        /         |          \                         /       \
                     51 57     58 59 5d    66 69 6b                6c 6d    70 73 76

    */

	deleteKey(pRoot, 0x66);
	cout << "删除key = 0x66" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x66后:
                                    51                                  6c
                                    /                                     \
                        51       58       69                           6c   70
                        /         |          \                        /       \
                     51 57    58 59 5d      69 6b                   6c 6d  70 73 76

    */

       deleteKey(pRoot, 0x69);
	cout << "删除key = 0x69" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x69后:
                                    51                                  6c
                                    /                                     \
                        51       58       5d                           6c   70
                        /         |          \                        /       \
                     51 57      58 59      5d 6b                    6c 6d  70 73 76

    */

       deleteKey(pRoot, 0x5d);
	cout << "删除key = 0x5d" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x5d后:
                                    51                         6c
                                    /                             \
                         51          58                         6c   70
                        /             \                        /       \
                     51 57          58 59 6b                 6c 6d  70 73 76

    */

       deleteKey(pRoot, 0x57);
	cout << "删除key = 0x57" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x57后:
                                    51                         6c
                                    /                             \
                         51          59                         6c   70
                        /             \                        /       \
                      51 58         59 6b                    6c 6d  70 73 76

    */

       deleteKey(pRoot, 0x58);
	cout << "删除key = 0x58" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x58后:
                                    51             6c           70
                                    /               |              \
                                51 59 6b         6c 6d          70 73 76
    */ 

       deleteKey(pRoot, 0x6d);
	cout << "删除key = 0x6d" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x6d后:
                                    51             6b           70
                                    /               |              \
                                   51 59          6b 6c         70 73 76
    */

	deleteKey(pRoot, 0x6b);
	cout << "删除key = 0x6b" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x6b后:
                                    51          6c        73
                                    /           |          \
                                   51 59      6c 70       73 76
    */

	deleteKey(pRoot, 0x76);
	cout << "删除key = 0x76" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x76后:
                                    51        6c        
                                    /           \         
                                   51 59      6c 70 73      
    */

	deleteKey(pRoot, 0x51);
	cout << "删除key = 0x51" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x51后:
                                    59        70        
                                    /           \         
                                   59 6c      70 73      
    */

	deleteKey(pRoot, 0x6c);
	cout << "删除key = 0x6c" << endl;
	DPSearch(pRoot);
	cout << endl;
	/*
	     删除0x6c后:  59 70 73 
    */


    return 0;
}


运行结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值