B树B+树

B树和B+树

B 树

B-tree(B-tree树即B树,B即Balanced,平衡的意思)这棵神奇的树是在Rudolf Bayer, Edward M. McCreight(1970)写的一篇论文《Organization and Maintenance of Large Ordered Indices》中首次提出的wikipedia中:http://en.wikipedia.org/wiki/B-tree,阐述了B-tree名字来源以及相关的开源地址,它在文件系统和数据库系统中使用较多,适用于组织动态的索引结构。它不是二叉树而是树,是一种多路平衡查找树。多路是指树的分支多余二叉,;平衡是指所有的叶子节点均在同一层上,以避免出现单支树的情况。要注意的是国内很多资料里称B树为B-树,这里的‘-’是英文的连字符,不是“B减树”。
以下是wikipedia中对B树的简述:
In computer science, a B-tree is a self-balancing tree data structure that keeps data sorted and allows searches, sequential access, insertions, and deletions in logarithmic time. The B-tree is a generalization of a binary search tree in that a node can have more than two children (Comer 1979, p. 123). Unlike self-balancing binary search trees, the B-tree is optimized for systems that read and write large blocks of data. B-trees are a good example of a data structure for external memory. It is commonly used in databases and filesystems.

B树的阶:树中所有节点的孩子节点的最大值就是B树的阶。通常用M表示,从查找效率来看, 通常取 M >= 3.

一个M阶的B树的定义如下:
该树或者是空树, 或者满足如下条件:

  • 树中每个结点最多含有m个孩子(m>=2);
  • 除根结点和叶子结点外,其它每个结点至少有[ceil(m / 2)]个孩子(其中ceil(x)是一个取上限的函数);
  • 若根结点不是叶子结点,则至少有2个孩子(特殊情况:没有孩子的根结点,即根结点为叶子结点,整棵树只有一个根节点);
  • 所有叶子结点都出现在同一层,叶子结点不包含任何关键字信息(可以看做是外部接点或查询失败的接点,实际上这些结点不存在,指向这些结点的指针都为null);
  • 每个非终端结点中包含有n个关键字信息: (n,P0,K1,P1,K2,P2,……,Kn,Pn)。其中:
    a) Ki (i=1…n)为关键字,且关键字按顺序升序排序K(i-1)< Ki。
    b) Pi为指向子树根的接点,且指针P(i-1)指向子树种所有结点的关键字均小于Ki,但都大于K(i-1)。
    c) 关键字的个数n必须满足: [ceil(m / 2)-1]<= n <= m-1。

B树的数据类型描述为:

#define m 20

typedef struct Node
{
int keyNum; //关键字的个数
int keys[m]; //关键字序列
struct Node *parent; //前驱域,插入删除时需要查询到前驱节点
struct Node *child[m]; //子节点序列
}mBTNode, *mBTree;

B树B+树_第1张图片

B树的查找:
基于B树的查找非常类似于二叉排序树的查找,但是在每个节点向下查找的时候,查找的路径不止两条,而是至少是m条。对根节点内有序存放的关键字序列可以用折半查找法查找, 也可以用顺序查找。具体如下:
若待查关键字为key,根节点内地i个关键字为Ki,则查找分为以下几种情况:
(1):若key = Ki,则查找成功;
(2):若key < Ki,则沿着P0所指的子树继续查找;
(3):若Ki < key < Ki+1,则沿指针Pi所指的子树继续查找;
(4):若key > Ki,则沿着指针Pn所指的子树继续查找;
(5):若直至查找的叶子节点还是没有查找的,则查找失败。

B树B+树_第2张图片

B树的插入:
插入一个元素时,首先在B树中是否存在,如果不存在,即在叶子结点处结束,然后在叶子结点中插入该新的元素,注意:如果叶子结点空间足够,这里需要向右移动该叶子结点中大于新插入关键字的元素,如果空间满了以致没有足够的空间去添加新的元素,则将该结点进行“分裂”,将一半数量的关键字元素分裂到新的其相邻右结点中,中间关键字元素上移到父结点中(当然,如果父结点空间满了,也同样需要“分裂”操作),而且当结点中关键元素向右移动了,相关的指针也需要向右移。如果在根结点插入新元素,空间满了,则进行分裂操作,这样原来的根结点中的中间关键字元素向上移动到新的根结点中,因此导致树的高
度增加一层。具体操作如下:
(1):如果该叶子节点的关键字总数小于m-1个,说明该节点还有空位置可以插入,B树的性质不会破坏;
(2):如果该叶子节点的关键字总数等于m-1个,说明该节点没有空位置可以插入了,此时插入操作会破坏B树的性质,必须进行分裂调整,过程如下:
a:以中间位置上的关键字为分裂点,将该节点分裂为两个节点;
b:将中间位置上的关键字向上插入到该节点的父节点上;
c:若双亲节点已满,则重复上述操作。

B树B+树_第3张图片

实际上,B树的创建就是利用B树的插入算法,从空树开始,逐渐插入关键字,从而创建一颗B树。
给定关键字序列{ 70, 45, 80, 20, 10, 30, 50, 655, 75, 90 },创建一个3阶B树的过程如下:
B树B+树_第4张图片

B树B+树_第5张图片

B树的删除:
B树的删除操作类似于插入操作,但比插入操作稍微复杂点。首先函数查找待删除节点,若查找失败不必删除,入找到,则进行删除操作:
(1):在叶子节点上删除key;
这种情况分三种:
a:若叶子节点的关键字个数大于[m/2]-1,则直接删除key不会破坏B树的性质;
B树B+树_第6张图片
b:若叶子节点个数等于[m/2]-1,则直接删除key会破坏B树的性质。若叶子节点的左(或者右)星弟节点中的关键字数目大于[m/2]-1,则将左兄弟节点上的最大关键字上移到父节点,而将父节点中大于(或者小于)上移关键字的关键字下移到叶子节点中,即“父子换位法”;
B树B+树_第7张图片
c:若叶子节点及相邻的左右节点关键字均等于[m/2]-1,则必须将叶子节点和左(或者右)兄弟合并。可以设叶子节点有右兄弟,在叶子节点中删除key后,将父节点中介于叶子节点和兄弟节点之间的关键字k座位中间关键字,并与二者一起合并为一个新节点,此时新节点中恰有2*[m/2]-2个关键字,仍然小于m-1个关键字,没有破坏B树的性质。但是由于父节点中删除了关键字k,若父亲节点中的关键字大于[m/2]-1,则删除操作结束,否则同样要与其左右兄弟合并,这个合并过程可能一直到根节点。
B树B+树_第8张图片
(2):非叶子节点上删除关键字key。
用key的中序前驱或者中序后继取代key,然后从叶子节点中删除该中序前驱或者中序后继节点。当删除完后可能出现上述的现象,按照上面的方法进行调整。

B+树

B+-tree:是应文件系统所需而产生的一种B-tree的变形树。
一棵m阶的B+树和m阶的B树的异同点在于:
1.有n棵子树的结点中含有n-1 个关键字; (此处颇有争议,B+树到底是与B 树n棵子树有n-1个关键字 保持一致,还是不一致:B树n棵子树的结点中含有n个关键字,待后续查证。暂先提供两个参考链接:①wikipedia 中B+树的介绍链接为:http://en.wikipedia.org/wiki/B%2B_tree#Overview;②http://hedengcheng.com/?p=525)
2.所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。 (而B 树的叶子节点并没有包括全部需要查找的信息)
3.所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含需要查找的有效信息)
B树B+树_第9张图片
B+树的优点:
1) B+-tree的磁盘读写代价更低
B+-tree的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘快。而B+ 树内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B 树就比B+ 树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。
2) B+-tree的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

参考书籍:《数据结构与算法》- 人民邮电出版社
参考博客:http://blog.csdn.net/u013400245/article/details/52824744
版权声明:如若转载,请声明出处

你可能感兴趣的:(数据结构与算法)