Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

多路搜索树

$
0
0

1.B-tree出现的意义

前面介绍了树的数据结构,但是用树对硬盘、磁带等二级存储设备上读写数据时,会有问题。我们都知道,I/O操作的基础单元是block,当需要从硬盘上读数据时,包含该数据的整个block都会读进内存。而二叉树的节点可能不在同一个block里,这样对树进行遍历时,就会进行多次的block更换。

如下图所示,不同的block用方框隔开。

 

B-Tree就能减少访问二级存储的时间,具体的原理是:B-Tree的一个节点可以有多个数据值,大小等于block,这样就可以充分利用每次读取的block,进行多个数值的比较。

2.A B-tree of Order m的定义

(1)根节点最少有两个子树(根节点是叶节点除外)

(2)既不是根节点又不是叶节点的内部节点有k-1个值和k个指向子树的引用,其中m/2<=k<=m(m/2是上限,即商+1)

(3)每个叶节点有k-1个值,其中m/2<=k<=m,没有指向子树的引用

(4)所有的叶节点在同一层

举例来说,A B-tree of order 7,则4<=k<=7,即每个内部节点有[3,6]个值,[4,7]个指向子树的引用。

 

3.B-tree的代码实现

3.1节点定义

从上述的定义中,可以看到多路搜索树的节点中存放了两个数组,一个数组存放节点中的值,另一个数组存放指向子树的引用

public class Node {

    int m = 7;//B-treeorder的值

    boolean isLeaf = true;//默认为叶节点

    int keyCount;//对节点中的key进行计数;

    int[] keys = new int[m-1];//存放每个节点的数值,最多有m-1个值

    Node[] refers = new Node[m];//存放指向子树的引用,最多有m个引用

    public Node(int i ){

       keys[0] = i;

       keyCount =1;

       for(int j = 0; j<m;j++){

           refers[j] = null;

       }

    }

}

3.2查找

    public Node search(int k,Node n){

       if(n!=null){

           int i = 0;

           for(;i<n.keyCount&&k>n.keys[i];i++);//找到比k大的值,进而到子树中进行比较

           if(k==n.keys[i])

              return n;

           else

              search(k,n.refers[i]);

       }

       return null;

    }

在该方法的实现中,用到了递归,即找出子树的正确位置后,再对子树进行相同的过程。上面的代码通过找到比k大的值,那么就进入k的左子树;如果该节点的所有值都比k小,则进入该节点的最后一个子树。

3.3插入

注:插入的操作只会发生在叶节点,因为非叶结点表示的是一个范围。主要考虑被插入的节点是否已满。

分为三种情况:

(1)在叶节点中插入,并且叶节点仍然有空间

(2)在叶节点中插入,但是叶节点已满,则找出该节点的中间值,然后将该节点分为两个子节点(除去了中间值),该中间值则放入父节点中,以此类推

(3)一直到了根节点,如果根节点也满,则按照(2)的方式将根节点分为两个子节点,并且中间值为新的根节点

为了简便起见,用伪码表示。

Insert(k)

         Finda leaf node to insert k;

         While(true)//跟递归的思想接近

        if(the node is not full)

                   insertk and increment keycount;

         else

                   findthe mid-key;

                   dividethe left keys into two nodes, node1 and node2;

                   if(thenode is the root)

                            root=newNode(mid-key)

                            return;

                   else

                            node=itsparent;//即再重复上述过程

 

4.B*-tree

从B-tree的定义可以知道,B-tree能够保证每个节点至少50%的full,那么另外的50%可能会浪费。有研究表明,经过一系列的插入删除操作后,B-tree大概69%的full,这之后再进行操作,这个概率的变化也会很小。

B*-tree是在B-tree基础上得到的,出了root,其他节点都要至少2/3full,好处是更加充分的利用空间。

5.B+-tree

B+-tree也是B-tree的一种变形,与B-tree不同的是:

(1)在B+-tree中,关键码只分布在叶节点中;所以会一直查到叶节点,进行的插入操作也是针对叶节点

(2)有两个头指针:一个指向根节点,可以进行自顶向下的随机搜索;一个指向关键码的最小的叶节点,进行顺序搜索。

作者:shanxing2 发表于2013-2-28 20:25:28 原文链接
阅读:3 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>