算法: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;
}

 

posted @ 2017-03-20 22:57  jmst  阅读(517)  评论(0编辑  收藏  举报