#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;
}
运行结果: