B_Tree 的数据结构

这篇具有很好参考价值的文章主要介绍了B_Tree 的数据结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

头文件(结构体定义与函数声明):

#ifndef BTREE_H_INCLUDED
#define BTREE_H_INCLUDED
#include<stdbool.h>
#include<stdlib.h>//NULL的头文件
#define m 3//BTree的阶每个节点至多有m棵子树且非终端节点至少有[m/2]棵子树
#define KeyType int
#define Record int
typedef enum{OK,ERROR}Status;
typedef struct BTNode
{
    int keynum;//节点中关键字的个数
    struct BTNode *parent;
    KeyType Key[m+1];//关键字向量0号单元未用
    struct BTNode* ptr[m+1];//子树指针向量
    Record* recptr[m+1];//记录指针向量0号单元未用
}BTNode,*BTree;//均多留出一个单元分裂时使用
typedef struct
{
    BTNode *pt;//指向找到的节点
    int i;//在节点中的关键字序号1到m
    int tag;//1查找成功0查找失败
}Result;//B树的查找结果类型

int Search(BTree p,KeyType K);
Result SearchBTree(BTree T,KeyType K);
void Insert(BTree q,int i,KeyType x,BTree ap);
void split(BTree q,int s,BTree ap);
void NewRoot(BTree *T,BTree p,KeyType x,BTree ap);
Status InsertBTree(BTree *T,KeyType K,BTree q,int i);
void Merge(BTree v);
void Delete(BTree v,int i);
Status DeleteBTree(BTree T,KeyType K);
#endif // BTREE_H_INCLUDED

函数实现

(需要在源文件即后缀为.c的文件中实现,否则编译器会报错,重复定义函数):

#include "BTree.h"
#include<math.h>
int s=ceil((double)m/2);

int Search(BTree p,KeyType K)
{
    int i;
    for(i=1;i<=p->keynum&&p->Key[i]<K;i++);
    if(p->Key[i]!=K)i--;
    return i;
}
Result SearchBTree(BTree T,KeyType K)
{
    BTree p=T;
    BTree q=NULL;
    bool found=false;int i=0;
    while(p&&!found)
    {
        i=Search(p,K);//在p->Key中查找使得p->Key[i]<=K<p->Key[i+1]
        if(i>0&&p->Key[i]==K)found=true;
        else
        {
            q=p;p=p->ptr[i];
        }
    }
    if(found)return (Result){p,i,1};
    else return (Result){q,i,0};
}
void Insert(BTree q,int i,KeyType x,BTree ap)
{
    int j;
    for(j=q->keynum;j>i;j--)
    {
        q->Key[j+1]=q->Key[j];
        q->ptr[j+1]=q->ptr[j];
        q->recptr[j+1]=q->recptr[j];
    }
    q->Key[i+1]=x;
    q->ptr[i+1]=ap;
    q->recptr[i+1]=NULL;
    if(ap!=NULL)
    {
        ap->parent=q;
    }
    q->keynum++;
    return;
}
void split(BTree q,int s,BTree ap)
{//ap将成为q的右兄弟
    ap=(BTree)malloc(sizeof(BTNode));
    ap->keynum=m-s;
    ap->parent=q->parent;
    for(int j=s+1;j<=m;j++)
    {
        ap->Key[j-s]=q->Key[j];
        ap->ptr[j-s]=q->ptr[j];
        ap->recptr[j-s]=q->recptr[j];
        if(q->ptr[j]!=NULL)
        {
            q->ptr[j]->parent=ap;
        }
    }
    q->keynum=s;
    if(q->parent!=NULL)
    {
        Insert(q->parent,Search(q->parent,q->Key[s]),q->Key[s],ap);
    }
    return;
}

void NewRoot(BTree *T,BTree p,KeyType x,BTree ap)
{
    BTree root=(BTree)malloc(sizeof(BTNode));
    root->parent=NULL;
    root->keynum=1;
    root->Key[1]=x;
    root->ptr[0]=p;
    root->ptr[1]=ap;
    root->recptr[0]=NULL;
    root->recptr[1]=NULL;
    p->parent=root;
    ap->parent=root;
    *T=root;
    return;
}
Status InsertBTree(BTree *T,KeyType K,BTree q,int i)
{
    KeyType x=K;bool finished=false;
    BTree ap=NULL;
    while(q&&!finished)
    {
        Insert(q,i,x,ap);//将x和ap分别插入q->Key[i+1]和q->ptr[i+1]
        if(q->keynum<m)finished=true;
        else//分裂节点
        {//s=m/2向上取整
            split(q,s,ap);
            x=q->Key[s];//将q->Key[s+1,m],q->ptr[s,m]和q->recptr[s+1,m]移入新节点*ap
            q=q->parent;
            if(q)i=Search(q,x);
        }
    }
    if(!finished)//T是空树或根节点已经分裂为节点关*q和*ap
        NewRoot(T,q,x,ap);//生成含信息(T,x,ap)的新的根节点关*T,原T和ap为子树指针
    return OK;
}
void Merge(BTree v)
{
    if(v->keynum>=s-1)return;
    BTree pt=v->parent;
    if(pt==NULL)return;
    int j;
    for(j=0;j<=pt->keynum;j++)if(pt->ptr[j]==v)break;
    BTree r=NULL,l=NULL;
    if(j<pt->keynum)r=pt->ptr[j+1];
    if(j>0)l=pt->ptr[j-1];

    if(r)
    {
        int k=v->keynum;
        v->ptr[++k]=r->ptr[0];
        v->recptr[k]=pt->recptr[j+1];
        v->Key[k]=pt->Key[j+1];
        for(int i=1;i<=r->keynum;i++)
        {//合并时不一定是终端节点所以需要考虑子树的改变
            v->Key[++k]=r->Key[i];
            v->ptr[k]=r->ptr[i];
            v->recptr[k]=r->recptr[i];
        }
        v->keynum=k;
        for(k=j+1;k<pt->keynum;k++)
        {
            pt->Key[k]=pt->Key[k+1];
            pt->ptr[k]=pt->ptr[k+1];
            pt->recptr[k]=pt->recptr[k+1];
        }
        pt->keynum--;
        Merge(pt);
    }
    else
    {
        int k=++l->keynum;
        l->ptr[k]=v->ptr[0];
        l->recptr[k]=pt->recptr[j];
        l->Key[k]=pt->Key[j];
        for(int i=1;i<=v->keynum;i++)
        {
            l->Key[++k]=v->Key[i];
            l->ptr[k]=v->ptr[i];
            l->recptr[k]=v->recptr[i];
        }
        l->keynum=k;
        for(int i=j;i<pt->keynum;i++)
        {
            pt->Key[i]=pt->Key[i+1];
            pt->recptr[i]=pt->recptr[i+1];
            pt->ptr[i]=pt->ptr[i+1];
        }
        pt->keynum--;
        Merge(pt);
    }
    return;
}
void Delete(BTree v,int i)
{
    BTree pt=v->parent;
    if(v->keynum>=s||pt==NULL)
    {//该节点的关键字数目不小于s
        for(int j=i;j<v->keynum;j++)
        {
            v->Key[j]=v->Key[j+1];
            v->recptr[j]=v->recptr[j+1];
        }
        v->keynum--;
    }
    else if(v->keynum==s-1)
    {
        int j;
        for(j=0;j<=pt->keynum;j++)
        {
            if(pt->ptr[j]==v)break;
        }
        BTree r=NULL,l=NULL;
        if(j<pt->keynum)r=pt->ptr[j+1];
        if(j>0)l=pt->ptr[j-1];

        if(r&&r->keynum>s-1)
        {
            int k;
            for(k=i;k<v->keynum;k++)
            {//此时v一定是终端节点所以不用考虑子树
                v->Key[k]=v->Key[k+1];
                v->recptr[k]=v->recptr[k+1];
            }
            v->Key[k]=pt->Key[j+1];
            pt->Key[j+1]=r->Key[1];
            Delete(r,1);
        }
        else if(l&&l->keynum>s-1)
        {
            int k;
            for(k=i;k>1;k--)
            {
                v->Key[k]=v->Key[k-1];
                v->recptr[k]=v->recptr[k-1];
            }
            v->Key[k]=pt->Key[j];
            pt->Key[j]=l->Key[l->keynum];
            l->keynum--;
        }
        else
        {
            for(int k=i;k<v->keynum;k++)
            {
            v->Key[k]=v->Key[k+1];
            v->recptr[k]=v->recptr[k+1];
            }
            v->keynum--;
            Merge(v);
        }
    }
    return;
}
Status DeleteBTree(BTree T,KeyType K)
{
    Result res=SearchBTree(T,K);
    if(res.tag==0)return ERROR;
    BTree v=res.pt;
    int i=res.i;

    if(v->ptr[0]==NULL)
    {//终端节点
        Delete(v,i);
    }
    else
    {//存在于内部节点
        BTree p=v->ptr[0];
        while(p->ptr[0]!=NULL)p=p->ptr[0];
        v->Key[i]=p->Key[1];
        Delete(p,1);
    }
    return OK;
}

最后在main源文件中只需要包含该头文件即可使用定义的抽象数据类型:

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

int main()
{
    printf("Hello world!\n");
    return 0;
}

这里没有提供具体样例,可根据实际情况自行编写。文章来源地址https://www.toymoban.com/news/detail-796512.html

到了这里,关于B_Tree 的数据结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构与算法 | 二叉树(Binary Tree)

    二叉树(Binary Tree)是一种树形数据结构,由节点构成,每个节点最多有两个子节点:一个左子节点和一个右子节点。 \\\"二叉树\\\"(Binary Tree)这个名称的由来是因为二叉树的每个节点最多有两个子节点,一个左子节点和一个右子节点。其中,“二叉”指的是两个,因此“二叉树

    2024年02月08日
    浏览(40)
  • 【数据结构基础】树 - 前缀树(Trie Tree)

    Trie,又称字典树、单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的

    2024年02月07日
    浏览(40)
  • Java 【数据结构】 二叉树(Binary_Tree)【神装】

        登神长阶  第五神装 二叉树 Binary-Tree 目录  🎷一.树形结构 🪗1.概念 🎸2.具体应用 🎹 二.二叉树(Binary Tree) 🎺1.概念  🎻2.表现形式 🪕3.特殊类型 🥁3.1完全二叉树(Complete Binary Tree) 🪘3.2满二叉树(Full Binary Tree) 🔋4.性质  🪫5.二叉树的遍历 💿5.1前中后序遍历

    2024年04月27日
    浏览(44)
  • 红黑树下岗,内核新数据结构上场:maple tree!

      在外界看来,Linux 内核的内部似乎变化很少,尤其是像内存管理子系统(memory-management subsystem)这样的子系统。然而,开发人员时常需要更换内部接口来解决某些长期存在的问题。比如,其中一个问题就是用来保护内存管理里的重要结构的锁的竞争问题,这些重要结构是指

    2024年02月04日
    浏览(46)
  • Element-UI控件Tree实现数据树形结构

            在前端开发中,有时会遇到所有菜单数据在同一级的情况,后端未对数据进行分级处理;但前端渲染需要是树状结构的数据,如何实现数据的树状化?将数组中通过父节点的ID与子节点的parentId关联,通过递归函数来实现。         前端框架这里使用element-ui的tree控件

    2024年02月05日
    浏览(103)
  • 区块链的数据结构(二)——默克尔树(Merkle Tree)

            区块链中的另外一个数据结构是Merkle tree,在比特币中使用的就是这种结构:         可能没有听说过Merkle tree,但一定听说过binary tree(二叉树)。         Merkle tree和binary tree的区别:Merkle tree用哈希指针代替了普通的指针         每个框内的两个哈希值

    2024年02月21日
    浏览(40)
  • Java学数据结构(2)——树Tree & 二叉树binary tree & 二叉查找树 & AVL树 & 树的遍历

    1.树的出现:解决链表线性访问时间太慢,树的时间复杂度O(logN); 2.二叉树的定义,最多两个儿子节点; 3.二叉查找树,左小,右大,中居中;remove方法,两种,只有一个儿子节点,有两个儿子节点; 4.AVL树,在二叉查找树基础上加平衡条件,旋转方法,单旋转,双旋转;

    2024年02月10日
    浏览(49)
  • 数据结构英文习题解析-第五章 二叉搜索树Binary Search Tree

    前言:最近快到FDS考试了,po重刷了一下学校的题目,自己整理了一些解析orz 因为po在自己找解析和学习的过程中非常痛苦,所以在此共享一下我的题目和自己写的解题思路,欢迎各位指出错误~全章节预计会陆续更新,可在专栏查看~ HW5 1.In a binary search tree, the keys on the same

    2024年04月09日
    浏览(48)
  • 浙大数据结构第四周之04-树6 Complete Binary Search Tree

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the node\\\'s key. The right subtree of a node contains only nodes with keys greater than or equal to the node\\\'s key. Both the left and right subtrees must also be binary search trees. A Comple

    2024年02月16日
    浏览(47)
  • 【数据结构与算法】-哈夫曼树(Huffman Tree)与哈夫曼编码

    超详细讲解哈夫曼树(Huffman Tree)以及哈夫曼编码的构造原理、方法,并用代码实现。 路径 :从树中一个结点到另一个结点之间的 分支 构成这两个结点间的路径。 结点的路径长度 :两结点间路径上的 分支数 。 树的路径长度: 从树根到每一个结点的路径长度之和。记作: TL  权

    2024年02月06日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包