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;
}


B树是一种自平衡的搜索树,常用于数据库和文件系统等数据结构中。在Java中,我们可以使用以下方式实现B树: 1. 定义B树节点类: ``` public class BTreeNode { public int[] keys; // 节点存储的关键字数组 public int t; // 最小度数 public BTreeNode[] children; // 子节点数组 public int n; // 节点关键字个数 public boolean leaf; // 是否为叶子节点 public BTreeNode(int t, boolean leaf) { this.t = t; this.leaf = leaf; this.keys = new int[2 * t - 1]; this.children = new BTreeNode[2 * t]; this.n = 0; } } ``` 2. 定义B树类: ``` public class BTree { private BTreeNode root; // B树根节点 private int t; // 最小度数 public BTree(int t) { this.t = t; this.root = null; } // 插入关键字 public void insert(int key) { if (root == null) { root = new BTreeNode(t, true); root.keys[0] = key; root.n = 1; } else { if (root.n == 2 * t - 1) { // 根节点已满,需要分裂 BTreeNode newRoot = new BTreeNode(t, false); newRoot.children[0] = root; splitChild(newRoot, 0, root); int i = 0; if (newRoot.keys[0] < key) { i++; } insertNonFull(newRoot.children[i], key); root = newRoot; } else { insertNonFull(root, key); } } } // 插入关键字(非满节点) private void insertNonFull(BTreeNode node, int key) { int i = node.n - 1; if (node.leaf) { while (i >= 0 && node.keys[i] > key) { node.keys[i + 1] = node.keys[i]; i--; } node.keys[i + 1] = key; node.n++; } else { while (i >= 0 && node.keys[i] > key) { i--; } i++; if (node.children[i].n == 2 * t - 1) { // 子节点已满,需要分裂 splitChild(node, i, node.children[i]); if (node.keys[i] < key) { i++; } } insertNonFull(node.children[i], key); } } // 分裂子节点 private void splitChild(BTreeNode parent, int i, BTreeNode node) { BTreeNode newNode = new BTreeNode(t, node.leaf); newNode.n = t - 1; for (int j = 0; j < t - 1; j++) { newNode.keys[j] = node.keys[j + t]; } if (!node.leaf) { for (int j = 0; j < t; j++) { newNode.children[j] = node.children[j + t]; } } node.n = t - 1; for (int j = parent.n; j >= i + 1; j--) { parent.children[j + 1] = parent.children[j]; } parent.children[i + 1] = newNode; for (int j = parent.n - 1; j >= i; j--) { parent.keys[j + 1] = parent.keys[j]; } parent.keys[i] = node.keys[t - 1]; parent.n++; } // 查找关键字 public boolean search(int key) { return search(root, key); } private boolean search(BTreeNode node, int key) { int i = 0; while (i < node.n && key > node.keys[i]) { i++; } if (i < node.n && key == node.keys[i]) { return true; } if (node.leaf) { return false; } return search(node.children[i], key); } } ``` 3. 测试B树: ``` public class Test { public static void main(String[] args) { BTree bTree = new BTree(3); bTree.insert(1); bTree.insert(3); bTree.insert(7); bTree.insert(10); bTree.insert(11); bTree.insert(13); bTree.insert(14); bTree.insert(15); bTree.insert(18); bTree.insert(16); bTree.insert(19); bTree.insert(24); bTree.insert(25); bTree.insert(26); bTree.insert(21); bTree.insert(4); bTree.insert(5); bTree.insert(20); bTree.insert(22); bTree.insert(2); bTree.insert(17); bTree.insert(12); System.out.println(bTree.search(15)); // true System.out.println(bTree.search(27)); // false } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值