算法:B树的实现
btree.h
#ifndef _BTREE_H #define _BTREE_H #define M 4 #define KEY_NUM (M*2-1) struct Node; typedef int KeyType; typedef struct Node *PtrToNode; typedef PtrToNode BTree; typedef PtrToNode Position; BTree BTree_Create(void); BTree BTree_Insert(BTree T,KeyType key); BTree BTree_Search(BTree T,KeyType key,int *index); BTree BTree_Delete(BTree T,KeyType key); #endif struct Node { int num; KeyType key[KEY_NUM-1]; KeyType child[KEY_NUM]; bool leaf; };
btree.c
#include <stdlib.h> #include <stdio.h> #include "BTree.h" BTree BTree_Split_Child(BTree Parent,int pos,BTree Child); BTree BTree_Insert_NoFull(BTree T,KeyType key); BTree BTree_Find_index(BTree T,KeyType key,int *ret); BTree BTree_Create(void) { Position T; if(!(T=malloc(sizeof(struct Node)))){ printf("out of space"); return NULL; } T->num=0; T->leaf=1; return T; } BTree BTree_Insert(BTree T,KeyType key) { if(T->num==KEY_NUM){ Position P; if(!(P=malloc(sizeof(struct Node)))){ printf("out of space"); return NULL; } P->num=0; P->leaf=0; P->child[0]=T; T=BTree_Split_Child(P,0,T); } return BTree_Insert_NoFull(T,key); } BTree BTree_Split_Child(BTree Parent,int pos,BTree Child) { Position Z; int i; if(!(Z=malloc(sizeof(struct Node)))){ printf("out of space"); return NULL; } Z->num=M-1; Z->leaf=Child->leaf; /*copy M key into Z*/ for(i=0;i<M-1;++i){ Z->key[i]=Child->key[i+M]; } /*copy M child into Z*/ for(i=0;i<M;++i){ Z->child[i]=Child->child[i+M]; } Child->num=M-1; for(i=Parent->num;i>pos;--i){ Parent->child[i+1]=Parent->child[i]; } Parent->child[pos+1]=Z; for(i=Parent->num-1;i>pos;--i){ Parent->key[i+1]=Parent->key[i]; } Parent->key[pos]=Child->key[M-1]; Parent->num++; return Parent; } BTree BTree_Insert_NoFull(BTree T,KeyType key) { int i=T->num-1; if(T->leaf){ while(i>0&&key<T->key[i]){ T->key[i+1]=T->key[i]; --i; } T->num++; }else{ while(i>0&&key<T->key[i]){ --i; } ++i; if(T->child[i]->num==KEY_UNM){ BTree_Split_Child(T,i,T->child[i]); } if(key>T->key[i]){ ++i; } return BTree_Insert_NoFull(T->child[i],key); } } BTree BTree_Search(BTree T,KeyType key,int *index) { int i; *index=-1; for(i=0;i<T->num&&key>T->key[i];++i) ; if(i<T->num&&key==T->key[i]){ *index=i; return T; } if(T->leaf){ return NULL; }else{ return BTree_Search(T->child[i],key); } } BTree BTree_Find_Index(BTree T,KeyType key,int *ret) { int i,num; for(i=0,num=T->num;i<num&&(*ret=key-T->key[i])<0;++i) ; /* *when out of loop,three conditions happens: *ret==0 means find the key, *ret>0&&i<num not found the key, *ret<0&&i==num not found the key and out of the key array range */ return i; } /* B树删除的逻辑比较复杂分析如下: *叶子节点 *未找到->直接返回 *找到节点->直接删除,返回 *非叶子节点 *找到节点 下属节点富有->替换父节点 下属节点不富有->合并父节点和左右子几点 *未找到节点并且当前节点不富有 兄弟节点富有->借用父节点,并且兄弟富有节点上移给父节点 兄弟节点不富有->合并父节点和兄弟节点 非叶子几点执行递归删除 */ BTree BTree_Delete(BTree T,KeyType key) { int index,i,ret; Position preceding,successor; Position child,sibling; index=BTree_Find_Index(T,key,&ret); if(T->leaf&&!ret){ /* case 1: if found the key and the key node is leaf then delete directly */ memmove(&T->key[index],&T->key[index+1],sizeof(KeyType) *(T->num-index-1)); --T->num; return T; } if(T->leaf&&ret){ return T; } /*btree include the key*/ if(!ret){ /* case 2: if find the key and the node is not leaf */ preceding=T->child[index]; successor=T->child[index+1]; if(preceding->num>=M){ /* case 2a */ replace=preceding->key[preceding->num-1]; T->child[index]=BTree_Delete(preceding,replace); T->key[index]=replace; return T; } if(successor->num>=M){ /* case 2b */ replace=successor->key[0]; T->child[index]=BTree_Delete(successor,replace); T->key[index]=replace; return T; } if((preceding->num==M-1)&&(successor->num==M-1)){ /* case 2c */ preceding->key[preceding->num++]=key; memmove(&preceding->key[preceding->num],&successor->key[0],sizeof(KeyType) *(successor->num)); memmove(&preceding->child[preceding->num],&successor->child[0],sizeof(KeyType) *(successor->num+1)); preceding->num+=successor->num; if(T->num-1>0){ memmove(&T->key[index],&T->key[index+1],sizeof(KeyType) *(T->num-index-1)); memmove(&T->child[index+1],&T->child[index+2],sizeof(KeyType) *(T->num-index-1)); }else{ free(T); T=preceding; } free(successor); BTree_Delete(preceding,key); return T; } } /*btree not include the key*/ if((child=T->child[index])&&child->num==M-1){ /* case 3: btree not include the key and child has M-1 keys */ if(index<T->num&&(sibling=T->child[index+1])&&(sibling->num>=M)){ /* case 3a */ child->key[child->num++]=T->key[index]; T->key[index]=sibling->key[0]; child->child[child->num]=sibling->child[0]; sibling->num--; memmove(&sibling->key[0],&sibling->key[1],sizeof(KeyType) *(sibling->num)); memmove(&sibling->child[0],&sibling->child[1],sizeof(KeyType) *(sibling->num+1)); }else if(index<T->num&&(sibling=T->child[index-1])&&(sibling->num>=M)){ memmove(&sibling->key[1],&sibling->key[0],sizeof(KeyType) *(sibling->num-1)); memmove(&sibling->child[1],&sibling->child[0],sizeof(KeyType) *(sibling->num)); child->key[0]=T->key[index]; T->key[index]=sibling->key[sibling->num-1]; child->child[0]=sibling->child[sibling->num]; sibling->num--; child->num++; }else if(index<T->num&&(sibling=T->child[index+1])&&(sibling->num==M-1)){ /* case 3b */ child->key[child->num++]=T->key[index]; memmove(&child->key[child->num],&sibling->key[0],sizeof(KeyType) *(sibling->num)); memmove(&child->child[child->num],&sibling->child[0],sizeof(KeyType) *(sibling->num+1)); child->num+=sibling->num; if(T->num-1>0){ memmove(&T->key[index],&T->key[index+1],sizeof(KeyType) *(T->num-index-1)); memmove(&T->child[index+1],&T->child[index+2],sizeof(KeyType) *(T->num-index)); T->num--; }else{ free(T); T=child; } free(sibling); }else if(index<T->num&&(sibling=T->key[index-1])&&(sibling->num==M-1)){ sibling->key[sibling->num++]=T->key[index]; memmove(&sibling->key[sibling->num],&child->key[0],sizeof(KeyType) *(child->num)); memmove(&sibling->child[sibling->num],&child->child[0],sizeof(KeyType) *(child->num+1)); sibling->num+=child->num; if(T->num-1>0){ memmove(&T->key[index-1],&T->key[index],sizeof(KeyType) *(T->num-index-1)); memmove(&T->child[index],&T->child[index+1],sizeof(KeyType) *(T->num-index)); T->num--; }else{ free(T); T=sibling; } child=sibling; } } /*递归执行删除*/ BTree_Delete(child,key); return T; }