B+樹的插入、刪除(附原始碼)
阿新 • • 發佈:2018-12-25
#include <stdio.h>
#include <stdlib.h>
#define MinDegree 4
typedef int ElementType;
typedef int* PtrElementType;
typedef enum Bool BoolType;
enum Bool{
False = 0,
True = 1
};
typedef struct TreeNode *PtrBpNode;
typedef struct TreeNode BpNode;
struct TreeNode{
int Num;
BoolType IsLeaf;
PtrElementType Key;
PtrBpNode *Child;
PtrBpNode Next;
};
typedef struct Tree *PtrBp;
struct Tree{
PtrBpNode Root;
};
PtrBpNode BpAllocateNode(BoolType IsLeaf);
void BpSpilitNode(PtrBpNode SpilitNodeP, int ChildIndex);
void BpInsertNonFull(PtrBpNode CurrentNode, ElementType Val);
void BpInsert(PtrBp T, ElementType Val);
void BpMerge(PtrBp T, PtrBpNode CurrentNode, int LeftIndex, int RightIndex);
void BpDelete(PtrBp T, PtrBpNode CurrentNode, ElementType Val);
void ShiftKey(PtrElementType Key, BoolType Direction, int Begin, int End);
void ShiftChild(PtrBpNode *Child, BoolType Direction, int Begin, int End);
int GetIndex(PtrElementType Key, int Size, ElementType Val);
void BpPrintTree(PtrBpNode Root);
void BpCreateTree(PtrBp T);
int main(){
PtrBp T = (PtrBp)malloc(sizeof(struct Tree));
T->Root = BpAllocateNode(True);
BpCreateTree(T);
//printf("B_Tree after delete 11:\n");
//BTDelete(T, T->Root, 11);
//BTPrintTree(T->Root);
printf("Bp_Tree after delete 16:\n");
BpDelete(T, T->Root, 16);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 18:\n");
BpDelete(T, T->Root, 18);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 20:\n");
BpDelete(T, T->Root, 20);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 19:\n");
BpDelete(T, T->Root, 19);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 0:\n");
BpDelete(T, T->Root, 0);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 5:\n");
BpDelete(T, T->Root, 5);
BpPrintTree(T->Root);
printf("Bp_Tree after delete 2:\n");
BpDelete(T, T->Root, 2);
BpPrintTree(T->Root);
return 0;
}
PtrBpNode BpAllocateNode(BoolType IsLeaf){
int i;
PtrBpNode NewNode = (PtrBpNode)malloc(sizeof(BpNode));
NewNode->Num = 0;
if(True == IsLeaf){
NewNode->IsLeaf = True;
}
else{
NewNode->IsLeaf = False;
}
NewNode->Key = (PtrElementType)malloc(sizeof(ElementType) * (MinDegree * 2 - 1));
NewNode->Child =(PtrBpNode*)malloc(sizeof(PtrBpNode) * MinDegree * 2);
for(i = 0; i < MinDegree * 2; i++){
NewNode->Child[i] = NULL;
}
NewNode->Next = NULL;
return NewNode;
}
void BpInsert(PtrBp T, ElementType Val){
PtrBpNode NewNode;
if(MinDegree * 2 - 1 == T->Root->Num){
NewNode = BpAllocateNode(False);
NewNode->Child[0] = T->Root;
T->Root = NewNode;
BpSpilitNode(NewNode, 0);
}
BpInsertNonFull(T->Root, Val);
}
void BpInsertNonFull(PtrBpNode CurrentNode, ElementType Val){
int Index = GetIndex(CurrentNode->Key, CurrentNode->Num, Val);
if(True == CurrentNode->IsLeaf){
ShiftKey(CurrentNode->Key, True, Index, CurrentNode->Num - 1);
CurrentNode->Key[Index] = Val;
(CurrentNode->Num)++;
}
else{
if(MinDegree * 2 - 1 == CurrentNode->Child[Index]->Num){
BpSpilitNode(CurrentNode, Index);
if(CurrentNode->Key[Index] < Val){
Index++;
}
}
BpInsertNonFull(CurrentNode->Child[Index], Val);
}
}
void BpSpilitNode(PtrBpNode SpilitNodeP, int ChildIndex){
int i;
PtrBpNode NewNode, SubNode = SpilitNodeP->Child[ChildIndex];
if(True == SubNode->IsLeaf){
NewNode = BpAllocateNode(True);
for(i = 0; i < MinDegree - 1; i++){
NewNode->Key[i] = SubNode->Key[i + MinDegree];
}
NewNode->Num = MinDegree - 1;
SubNode->Num = MinDegree;
NewNode->Next = SubNode->Next;
SubNode->Next = NewNode;
}
else{
NewNode = BpAllocateNode(False);
for(i = 0; i < MinDegree - 1; i++){
NewNode->Key[i] = SubNode->Key[i + MinDegree];
}
for(i = 0; i < MinDegree; i++){
NewNode->Child[i] = SubNode->Child[i + MinDegree];
}
NewNode->Num = SubNode->Num = MinDegree - 1;
}
ShiftKey(SpilitNodeP->Key, True, ChildIndex, SpilitNodeP->Num - 1);
ShiftChild(SpilitNodeP->Child, True, ChildIndex + 1, SpilitNodeP->Num);
SpilitNodeP->Key[ChildIndex] = SubNode->Key[MinDegree - 1];
SpilitNodeP->Child[ChildIndex + 1] = NewNode;
(SpilitNodeP->Num)++;
}
void ShiftKey(PtrElementType Key, BoolType Direction, int Begin, int End){
int i;
if(True == Direction){
for(i = End; i >= Begin; i--){
Key[i + 1] = Key[i];
}
}
else{
for(i = Begin; i <= End; i++){
Key[i - 1] = Key[i];
}
}
}
void ShiftChild(PtrBpNode *Child, BoolType Direction, int Begin, int End){
int i;
if(True == Direction){
for(i = End; i >= Begin; i--){
Child[i + 1] = Child[i];
}
}
else{
for(i = Begin; i <= End; i++){
Child[i - 1] = Child[i];
}
}
}
int GetIndex(PtrElementType Key, int Size, ElementType Val){
int i;
for(i = 0; i < Size; i++){
if(Key[i] >= Val){
break;
}
}
return i;
}
void BpDelete(PtrBp T, PtrBpNode CurrentNode, ElementType Val){
int Index = GetIndex(CurrentNode->Key, CurrentNode->Num, Val);
PtrBpNode Precursor, SubNode, Successor;
if(Index < CurrentNode->Num && Val == CurrentNode->Key[Index]){
if(True == CurrentNode->IsLeaf){
ShiftKey(CurrentNode->Key, False, Index + 1, CurrentNode->Num - 1);
(CurrentNode->Num)--;
return;
}
else{
Precursor = CurrentNode->Child[Index];
Successor = CurrentNode->Child[Index + 1];
if(Precursor->Num >= MinDegree){
if(True == SubNode->IsLeaf){
CurrentNode->Key[Index] = Precursor->Key[SubNode->Num - 2];
}
else{
CurrentNode->Key[Index] = Precursor->Key[SubNode->Num - 1];
}
BpDelete(T, Precursor, Precursor->Key[SubNode->Num - 1]);
}
else if(Successor->Num >= MinDegree){
CurrentNode->Key[Index] = Successor->Key[0];
if(True == SubNode->IsLeaf){
SubNode->Key[SubNode->Num - 1] = CurrentNode->Key[Index];
}
BpDelete(T, Successor, Successor->Key[0]);
}
else{
BpMerge(T, CurrentNode, Index, Index + 1);
BpDelete(T, Precursor, Val);
}
}
}
else{
if(True == CurrentNode->IsLeaf){
return;
}
else{
if(Index > 0){
Precursor = CurrentNode->Child[Index - 1];
}
SubNode = CurrentNode->Child[Index];
if(Index < CurrentNode->Num){
Successor = CurrentNode->Child[Index + 1];
}
if(SubNode->Num >= MinDegree){
BpDelete(T, SubNode, Val);
}
else{
if(Index > 0 && Precursor->Num >= MinDegree){
ShiftKey(SubNode->Key, True, 0, SubNode->Num - 1);
SubNode->Key[0] = CurrentNode->Key[Index - 1];
if(True == SubNode->IsLeaf){
CurrentNode->Key[Index - 1] = Precursor->Key[Precursor->Num - 2];
}
else{
CurrentNode->Key[Index - 1] = Precursor->Key[Precursor->Num - 1];
ShiftChild(SubNode->Child, True, 0, SubNode->Num);
SubNode->Child[0] = Precursor->Child[Precursor->Num];
}
(SubNode->Num)++;
(Precursor->Num)--;
BpDelete(T, SubNode, Val);
}
else if(Index < CurrentNode->Num && Successor->Num >= MinDegree){
if(True == SubNode->IsLeaf){
SubNode->Key[SubNode->Num] = Successor->Key[0];
}
else{
SubNode->Key[SubNode->Num] = CurrentNode->Key[Index];
}
CurrentNode->Key[Index] = Successor->Key[0];
SubNode->Child[SubNode->Num + 1] = Successor->Child[0];
(SubNode->Num)++;
ShiftKey(Successor->Key, False, 1, Successor->Num - 1);
ShiftChild(Successor->Child, False, 1, Successor->Num);
(Successor->Num)--;
BpDelete(T, SubNode, Val);
}
else{
if(Index > 0){
BpMerge(T, CurrentNode, Index - 1, Index);
BpDelete(T, Precursor, Val);
}
else{
BpMerge(T, CurrentNode, Index, Index + 1);
BpDelete(T, SubNode, Val);
}
}
}
}
}
}
void BpMerge(PtrBp T, PtrBpNode CurrentNode, int LeftIndex, int RightIndex){
int i;
PtrBpNode LeftNode = CurrentNode->Child[LeftIndex];
PtrBpNode RightNode = CurrentNode->Child[RightIndex];
if(True == LeftNode->IsLeaf){
for(i = 0; i < MinDegree - 1; i++){
LeftNode->Key[i + MinDegree - 1] = RightNode->Key[i];
}
LeftNode->Num = MinDegree * 2 - 2;
LeftNode->Next = RightNode->Next;
}
else{
for(i = 0; i < MinDegree - 1; i++){
LeftNode->Key[i + MinDegree] = RightNode->Key[i];
}
for(i = 0; i < MinDegree; i++){
LeftNode->Key[i + MinDegree] = RightNode->Key[i];
}
LeftNode->Key[MinDegree - 1] = CurrentNode->Key[LeftIndex];
LeftNode->Num = MinDegree * 2 - 1;
}
ShiftKey(CurrentNode->Key, False, LeftIndex + 1, CurrentNode->Num - 1);
ShiftChild(CurrentNode->Child, False, RightIndex + 1, CurrentNode->Num);
(CurrentNode->Num)--;
if(CurrentNode == T->Root && 0 == CurrentNode->Num){
T->Root = LeftNode;
}
}
void BpPrintTree(PtrBpNode Root){
int i;
if(NULL == Root){
return;
}
putchar('[');
for(i = 0; i < Root->Num; i++){
printf("%d", Root->Key[i]);
if(i != Root->Num - 1){
putchar(' ');
}
}
putchar(']');
printf("%d ", Root->IsLeaf);
printf("%d", Root->Num);
putchar('\n');
for(i = 0; i <= Root->Num; i++){
BpPrintTree(Root->Child[i]);
}
}
void BpCreateTree(PtrBp T){
int i;
int a[] = {12,1,9,2,0,11,7,19,4,15,18,5,14,13,10,16,6,3,8,17,20,21,23};
for(i = 0; i < 23; i++){
BpInsert(T, a[i]);
BpPrintTree(T->Root);
printf("The End\n");
}
}