c语言B树深入理解
B树是为磁盘或其他直接存储设备设计的一种平衡查找树。如下图所示。每一个结点箭头指向的我们称为入度,指出去的称为出度。树结构的结点入度都是1,不然就变成图了,所以我们一般说树的度就是指树结点的出度,也就是一个结点的子结点个数。有了度的概念我们就简单定义一下B树(假设一棵树的最小度数为M): 我们看看它的结点的结构,如下图所示: 每个结点存放着关键字和指向子结点的指针,很容易看出指针比关键码多一个。 由B树的定义我们可以看出它的一些特点: B树结点的大小怎么确定呢?为了最小化磁盘操作,通常把结点大小设为一个磁盘页的大小。一般树的高度不会超过3层,也就是说,查找一个关键码只需要3次磁盘操作就可以了。 在实现的时候其实还做了简化,每个结点除了包含关键码和指针外,还应该有该关键码所对应记录所在文件的信息的,比如文件偏移量,要不然怎么找到这条记录呢。在实现的时候这个附加数据就没有放在结点里面了,下面是定义树的结构,文件名为btrees.h,内容如下: 复制代码 代码如下: # include <stdio.h> # include <stdlib.h> # include "btrees.h" /* 给一个结点分配空间 */ struct btnode * allocateNode( struct btnode *ptr){ int i,max; ptr = ( struct btnode *) malloc ( sizeof ( struct btnode)); if (!ptr){ printf ( "allocated error!/n" ); exit (1); } max = 2*M; for (i=0; i<max; i++) ptr->p[i] = NULL; /* 初始化指针 */ memset (ptr->k,(max-1)* sizeof ( int )); /* 初始化键的值*/ return ptr; } /* 创建一个空的B树,就一个根结点 */ struct btnode * btreeCreate( struct btnode *root){ root = allocateNode(root); root->keyNum = 0; root->isleaf = 1; return root; } B树的插入都是在叶子结点进行的,由于B树的结点中关键码的个数是有限制的,最小度数为M的B树的结点个数是从M-1到2M-1个。比如下图是最小度数为2的B树(又称为2-3树),如下图所示,它的结点的个数就是1-3个。 先定位到要插入的位置,如果叶子结点的关键码个数还没达到上限,比如插入32,就比较简单,直接插入就行;如果叶子结点的关键码数到达了上限,就要分裂成2个子结点,把中间的关键码往上放到父节点中。但有极端的情况,就是父结点也是满的,就需要再次分裂,可能最后要把根结点也分裂了。但是这种算法不太好实现。 在《算法导论》中实现用的是另外一种思想,就是先分裂,在查找插入位置的过程中,如果发现有满的结点,就先把它分裂了,这就保证了在最后叶结点上插入数据的时候,这个叶结点的父结点总是不满的。下面我们看一个例子: 我们用逐个结点插入的方法创建一棵B树,结点顺序分别是{18,31,12,10,15,48,45,47,50,52,23,30,20},我们看看具体过程: 3.同理插入31和12,都比较简单,如下所示: 4.插入10,这时候根结点是满的,就要分裂,由于根结点比较特殊,没有父结点,就要单独处理,先生成一个空结点做为新的根结点,再进行分裂,如下所示: 5.再插入15,48,45,由于非满,直接插入,如下所示: 6.插入47,这次叶结点满了,就要先分裂,再插入,如下所示: 其他都是同样的道理,就不赘述了,下面是源码,加入到btree.c中,最后写了个main函数和一个广度优先显示树的方法,大家可以自己对比结果,代码的实现参照了《算法导论》和博客 http://hi.baidu.com/kurt023/blog/item/4c368d8b51c59ed3fc1f10cc.html 他博客里面已经实现了,只是在定义B树的时候指针数和关键码数成一样了,我于是自己重写了一下。 运行结果:同样一批关键码用不同算法生成的B树可能是不同的,比如4个关键码的结点[1,2,3,4]分裂的时候,把2或3放上去都可以;同样的算法插入顺序不同也可能不同。 附件中是源码,在Linux下编译通过。 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- SqlServer和Oracle中一些常用的sql语句8 触发器和事务
- SQL Server EXEC(EXECUTE)函数访问INSERTED或DELETED的内部
- An explicit value for the identity column in table '
- sql – @@ IDENTITY之后,INSERT语句总是返回0
- sql-server – 在Sql Server中转换为日期时间MM / dd / yyy
- T-SQL篇如何防止SQL注入的解决方法
- 是否可以在sql-server中备份和恢复数据库的一部分?
- 关于SQLServer2000的全文检索使用心得
- SQLServer2000同步复制技术实现步骤
- MySQL主从同步、读写分离配置步骤
- sql-server – SQL Server登录前握手
- 解决SQLSERVER在还原数据时出现的“FILESTREAM功
- sql-server – 如何在SQL Server 2005中存储时区
- SQLServer触发器创建、删除、修改、查看示例代码
- sql – 是否存在版本控制数据库存储引擎?
- Codematic .Net代码自动生成器(原名:LTP.Net代码
- sql-server-2008 – 在Management Studio和Profi
- 关于sqlserver身份登录失败的解决方法
- sql – 创建一个在Teradata中具有“with recursi
- MySQL性能全面优化方法参考,从CPU,文件系统选择到