B树数据结构的实现

来源:互联网 发布:网络歌曲2006 编辑:程序博客网 时间:2024/06/09 19:45

B树其实就是多路平衡树,主要用于外存储的一种数据结构。


B树的代码实现,主要参考《算法导论》,在看之前,自己尝试写了三遍,都不理想。

主要在于结点的插入和删除操作,如何不需要任何回溯。

给出代码如下:

#include "BTree.h"
#include <stdlib.h>
#include <stdio.h>


#define DEBUG_TREE
#ifdef DEBUG_TREE
#define Debug(x...)    printf(x)
#else
#define Debug(x...)
#endif

/*
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
*/

#define M 2 /*M为B树的最小度数,每个非根的结点至少有t-1个关键字,每个非根的内结点至少有t个子女。每个结点至多有2t-1个关键字,一个内结点至多有2t个子女(t>=1)*/



struct BTreeNode
{
    int num;//当前节点中键的数目
    int leaf;//如果该结点是叶子,leaf为TRUE;如果该结点为内结点,为FALSE
    void *key[2*M-1];//键
    
    struct BTreeNode *p[2*M];//指向子结点的指针
};

void print_int( BTree Tree )
{
    int i;
    for( i =0; i < Tree->num; i++)
    {
        printf("%d ",(int )Tree->key[i]);
    }
        
}

BTree Create( void )
{
    BTree x;
    x = (BTree *)malloc(sizeof(struct BTreeNode));
    x->leaf = 1;//TRUE;
    x->num = 0;
    return x;
}

BTree Search( BTree x, void *k)
{
    int i = 0;

}

BTree Split_Child( BTree x, int i, BTree y)
{
    int j;
    BTree z;
    z = (BTree *)malloc(sizeof(struct BTreeNode));
    z->leaf = y->leaf;
    z->num = M-1;
    for( j = 0; j < M-1; j++)
        z->key[j] = y->key[j+M];
    if( !(y->leaf) )
        for( j = 0; j < M; j++)
            z->p[j] = y->p[j+M];
    y->num = M-1;
    for( j = x->num; j > i; j--)
        x->p[j+1] = x->p[j];
    x->p[i+1] = z;
    for( j = x->num-1; j > i-1; j--)
        x->key[j+1] = x->key[j];
    x->key[i] = y->key[M-1];
    x->num += 1;

    return x;
}

BTree Insert( BTree T, void *key)
{
    if( T->num == 2*M-1 )
    {
        BTree s;
        s = (BTree *)malloc(sizeof(struct BTreeNode));
        s->leaf = 0;//FALSE;
        s->num = 0;
        s->p[0] = T;
        s = Split_Child(s,0,T);
        s = Insert_Nonfull(s,key);
        return s;
    }
    else
    {
        T = Insert_Nonfull(T,key);
        return T;
    }

}

BTree Insert_Nonfull( BTree x, void *key)
{
    int i;
    i = x->num;
    if( x->leaf )
    {
        while( i >= 1 && key < x->key[i-1] )
        {
            x->key[i] = x->key[i-1];
            i--;
        }
        x->key[i] = key;
        x->num += 1;
    }
    else
    {
        while( i >= 1 && key < x->key[i-1])
        {
            i--;
        }
        
        if( x->p[i]->num == 2*M-1 )
        {
            Split_Child(x,i,x->p[i]);
            if( key > x->key[i] )
                i += 1;    
        }
        Insert_Nonfull(x->p[i],key);    
    }
    return x;

}

//合并
BTree Merge_Child( BTree x, int i, BTree y, BTree z )
{
    int j;
    y->num = 2*M - 1;
    for( j = M; j < 2*M - 1; j++)
    {
        y->key[j] = z->key[j-M];    
    }
    y->key[M-1] = x->key[i];

    if( !( y->leaf ) )
    {
        for( j = M; j <= 2*M - 1; j++)
        {
            y->p[j] = z->p[j-M];
        }
    }

    for( j = i + 1; j < x->num; j++)
    {
        x->key[j-1] = x->key[j];
        x->p[j] = x->p[j+1];
    }
    x->num -= 1;
}

//查找前驱
BTree Search_PreDecessor( BTree y)
{
    int i;
    BTree x;
    x = (BTree *)malloc(sizeof(struct BTreeNode));
    x = y;
    i = x->num;
    while( !(x->leaf) )
    {
        x = x->p[i];
        i = x->num;
    }
    return x->key[i-1];
}

//查找后继
BTree Search_Successor( BTree z)
{
    BTree x;
    x = (BTree *)malloc(sizeof(struct BTreeNode));
    x = z;
    while( !(x->leaf) )
    {
        x = x->p[0];    
    }
    return x->key[0];
}

//转移到右边的子结点
BTree Shift_To_Right_Child( BTree x, int i, BTree y, BTree z )
{
    int j;
    z->num += 1;
    j = z->num - 1;
    while( j > 0 )
    {
        z->key[j] = z->key[j-1];
        j -= 1;
    }
    z->key[0] = x->key[i];
    x->key[i] = y->key[y->num-1];
    if( !(z->leaf) )
    {
        j = z->num;
        while( j > 0 )
        {
            z->p[j] = z->p[j-1];
            j -= 1;
        }
        z->p[0] = y->p[y->num];

    }
    y->num -= 1;
}

//转移到左边的子结点
BTree Shift_To_Left_Child( BTree x, int i, BTree y, BTree z )
{
    int j;
    y->num += 1;
    y->key[y->num-1] = x->key[i];
    x->key[i] = z->key[0];
    
    j = 1;
    while( j < z->num )
    {
        z->key[j-1] = z->key[j];
        j += 1;
    }
    if( !(z->leaf) )
    {
        y->p[y->num] = z->p[0];
        j = 1;
        while( j <= z->num )
        {
            z->p[j-1] = z->p[j];
            j += 1;
        }
        
    }
    z->num -= 1;    
    
}

BTree Delete_Nonone( BTree x, void *key)
{
    int i,j;
    i = 1;
    int prev,next;
    BTree y,z,p;
    y = (BTree *)malloc(sizeof(struct BTreeNode));
    z = (BTree *)malloc(sizeof(struct BTreeNode));
    p = (BTree *)malloc(sizeof(struct BTreeNode));

    if( x->leaf )   //如果在叶子结点,直接删除
    {
        while( i <= x->num && key > x->key[i-1] )
            i++;
        if( key == x->key[i-1] )
        {
            for( j = i; j < x->num; j++)
            {
                x->key[j-1] = x->key[j];
            }
            x->num -= 1;

        }
        else
            perror("wrong\n");
    }
    else    //在内结点中
    {
        while( i <= x->num && key > x->key[i-1] )
            i++;
        y = x->p[i-1];
        if( i <= x->num )
            z = x->p[i];
        if( key == x->key[i-1] )
        {
            if( y->num > (M-1) )
            {
                prev = Search_PreDecessor(y);
                Delete_Nonone(y,prev);
                x->key[i-1] = prev;
            }
            else if( z->num > (M-1) )
            {
                next = Search_Successor(z);
                Delete_Nonone(z,next);
                x->key[i-1] = next;
            }
            else
            {
                Merge_Child(x,i-1,y,z);
                //Delete_Nonode(y,key);
                
            }
        }
        else
        {
            if( i > 1 )    
                p = x->p[i-2];
            if( y->num == M-1 )
            {
                if( i > 1 && p->num > M-1 )
                    Shift_To_Right_Child(x,i-2,p,y);
                else if( i <= x->num && z->num > M-1 )
                    Shift_To_Left_Child(x,i-1,y,z);
                else if( i > 1 )
                {
                    Merge_Child(x,i-2,p,y);
                    y = p;
                }
                else
                {
                    Merge_Child(x,i-1,y,z);    
                }
                Delete_Nonone(y,key);
            }
            else
            {
                Delete_Nonone(y,key);    
            }
            
        }
        
    }
}

BTree Delete( BTree x, void *key )
{
    BTree y,z;
    y = (BTree *)malloc(sizeof(struct BTreeNode));
    z = (BTree *)malloc(sizeof(struct BTreeNode));

    if( x->num == 1 )
    {
        y = x->p[0];
        z = x->p[1];
        if( y->num == M-1 && z->num == M-1 )
        {
            Merge_Child(x,0,y,z);
            Delete_Nonone(y,key);
            return y;
        }
        else
        {
            Delete_Nonone(x,key);
            return x;
        }
    }
    else
    {
        Delete_Nonone(x,key);
        return x;
    }
}




int Tree_node_pre_order( BTree Tree, TreePrintData Tree_Print_Data )
{
    
    int i;
    Tree_Print_Data(Tree);
    printf("\n");    

    for( i = 0; i <= Tree->num; i++)
    {
        if( NULL != Tree->p[i] )
        {
            
            Tree_node_pre_order(Tree->p[i],Tree_Print_Data);
            //if( i == Tree->num)
            //    printf("       end");
        }

    }
    
        printf("\n");

    return 1;

}



原创粉丝点击