14.B树

B树

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

#define TRUE 1
#define FALSE 0

#define T 4

typedef struct B_Tree_Node
{
	int n;//指示该结点的关键字个数  
	int *keys;//该结点关键字数组
	int isLeaf;//该结点是否是叶子结点
	struct B_Tree_Node **child;//该结点的所有孩子结点
	struct B_Tree_Node *p; //该结点的父结点
}B_Tree_Node,*p_B_Tree_Node;

//生成一个新的B树结点
B_Tree_Node *alloact_Node()
{
	int i;
	B_Tree_Node *newNode=(B_Tree_Node *)malloc(sizeof(B_Tree_Node));
	newNode->n=0;
	newNode->isLeaf=TRUE;
	newNode->keys=(int *) malloc((2*T-1) * sizeof(int));
	newNode->child=(p_B_Tree_Node *) malloc((2*T) * sizeof(p_B_Tree_Node));
	newNode->p=NULL;
	for(i=0;i<2*T;i++)
		newNode->child[i]=NULL;
	return newNode;
}

//splitNode_p是被分裂结点的父结点,i是索引为i的孩子为满,需要被分裂  
//被分裂的结点是满的,那么它的n = 2*T - 1;被分裂为两个T-1个关键字的子结点,同时它的中间元素被提升到其父节点中  
void BTree_Child_Split(B_Tree_Node *splitNode_p, int index_child)  
{  
	int i;
    B_Tree_Node *newChild = alloact_Node();  
    newChild->n = T-1;  
    for(i = 0;i<T-1;i++)  
    {  
        newChild->keys[i] = splitNode_p->child[index_child]->keys[T+i];  
    }  
    splitNode_p->child[index_child]->n = T-1;  
    if(splitNode_p->child[index_child]->isLeaf!=TRUE)  //如果它的第i个孩子不是叶子结点,则将它的后T个孩子也送给newChild  
    {  
        newChild->isLeaf = FALSE;  
        for(i=0;i<T-1;i++)  
            newChild->child[i] = splitNode_p->child[i+T];  
    }  
    //将newChild 添加为splitNode_p的第i+1个孩子结点,将中间关键字提升到它中  
    for(i = splitNode_p->n; i>=index_child;i--)  
    {  
        splitNode_p->child[i+1] = splitNode_p->child[i];  
    }  
    splitNode_p->n++;  
    splitNode_p->child[index_child+1] = newChild;  
    for(splitNode_p->n-1; i>=index_child;i--)  
    {  
        splitNode_p->keys[i+1] = splitNode_p->keys[i];  
    }  
    splitNode_p->keys[index_child] = splitNode_p->child[index_child]->keys[T-1];  
}  

//在未满的结点插入元素
void BTree_Insert_NonFull(B_Tree_Node *nonfull, int k)  
{  
    int i = nonfull->n - 1;  
    if(nonfull->isLeaf)  
    {  
        while(i>=0&&k<nonfull->keys[i])  
        {  
            nonfull->keys[i+1] = nonfull->keys[i];  
            i--;  
        }  
        i = i+1;  
        (nonfull->n)++;  
        nonfull->keys[i] = k;  
    }  
    else  
    {  
        while(i>=0&&k<nonfull->keys[i])  
            i--;  
        i = i+1;  
        if(nonfull->child[i]->n == 2*T-1)  
        {  
            BTree_Child_Split(nonfull,i);  
            if(k>nonfull->keys[i])  
                i = i+1;  
        }  
        BTree_Insert_NonFull(nonfull->child[i],k);  
    }  
}  

//在B_Tree中加入新的关键字,主要由BTree_Insert_NonFull来实现,确保每次插入时所访问的结点都是非满结点;  
//首先,若根结点为满,则分裂根结点  
void BTree_Insert_Node(p_B_Tree_Node *root,int k)  
{  
    B_Tree_Node *p = *root;  
    if(p->n == 2*T - 1) //如果根结点满  
    {  
        B_Tree_Node *newRoot =alloact_Node();  
        newRoot->child[0] = (*root);  
        newRoot->isLeaf = FALSE;  
        *root = newRoot;  
          
        BTree_Child_Split(newRoot,0);  
        BTree_Insert_NonFull(newRoot,k);  
    }  
    else   
        BTree_Insert_NonFull(*root,k);  
}  

//广度优先搜索遍历输出
void printBFS(B_Tree_Node *t)  
{  
	int i;
    if(NULL == t)  
        return;  
  
    //输出当前节点所有关键字  
    printf("    [");  
    for(i = 0;i < t->n;++i)  
    {  
        printf("%d", t->keys[i]);  
        if(t->n - 1 != i)  
           printf(" ");  
    }  
    printf("]\n");  
  
    //递归输出所有子树  
    for(i = 0;i <= t->n;++i)  
        printBFS(t->child[i]);
}  

//构造B树
void createBTree(p_B_Tree_Node *root)  
{  
	int i;
    int a[] = {12,1,9,2,0,11,7,19,4,15,18,5,14,13,10,16,6,3,8,17};  
    for(i = 0;i<20;i++)  
    {  
        BTree_Insert_Node(root,a[i]);  
		printf("插入元素%d后\n",a[i]);
        printBFS(*root);  
    }  
}  

int main()
{
	B_Tree_Node *root; //B树根结点 
	root = alloact_Node(); 
	//构造B树
	createBTree(&root); 

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值