📜  B树介绍

📅  最后修改于: 2021-04-17 09:23:44             🧑  作者: Mango

介绍:
B树是一种自平衡搜索树。在大多数其他自平衡搜索树(如AVL和红黑树)中,假定所有内容都在主内存中。要了解B树的用法,我们必须考虑无法容纳在主存储器中的大量数据。当键的数量很大时,将以块的形式从磁盘读取数据。与主存储器访问时间相比,磁盘访问时间非常高。使用B树的主要思想是减少磁盘访问次数。大多数树操作(搜索,插入,删除,最大,最小,.. etc等)都需要O(h)磁盘访问,其中h是树的高度。 B树是一棵胖树。通过将最大可能的键放在B树节点中,B树的高度保持较低。通常,B树节点大小保持等于磁盘块大小。由于B树的高度较低,因此与AVL树,红黑树等平衡的二叉搜索树相比,大多数操作的总磁盘访问量显着减少。
B树的时间复杂度:

Sr. No. Algorithm Time Complexity
1. Search O(log n)
2. Insert O(log n)
3. Delete O(log n)

“ n”是B树中元素的总数。
B树的属性:

  1. 所有叶子处于同一水平。
  2. B树由术语最小度“ t”定义。 t的值取决于磁盘块的大小。
  3. 除根节点外,每个节点都必须至少包含(天花板)([t-1] / 2)个键。根目录可能至少包含1个密钥。
  4. 所有节点(包括根)最多可以包含t – 1个密钥。
  5. 节点的子代数等于该节点中的键数加1。
  6. 节点的所有键都按升序排序。两个键k1和k2之间的子项包含k1和k2范围内的所有键。
  7. B树从根开始生长和收缩,这与二叉搜索树不同。二叉搜索树向下生长,并且也从向下收缩。
  8. 像其他平衡二叉搜索树一样,搜索,插入和删除的时间复杂度为O(log n)。

以下是最小阶数为5的B树的示例。请注意,在实际的B树中,最小阶数的值远远大于5。

在上图中,我们可以看到所有叶节点都处于同一级别,并且所有非叶节点都没有空的子树,并且其键数小于其子节点数。
有趣的事实:

  1. 可以存在n个节点并且m是一个节点可以拥有的最大子节点数的B树的最小高度为: h_{min} =\lceil\log_m (n + 1)\rceil - 1

2.可以有n个节点存在的B树的最大高度,而d是非根节点可以拥有的最小子级数目: h_{max} =\lfloor\log_t\frac {n + 1}{2}\rfloor         t = \lceil\frac {m}{2}\rceil
B树中的Traversel:
遍历也类似于二叉树的有序遍历。我们从最左边的子项开始,递归打印最左边的子项,然后对剩余的子项和键重复相同的过程。最后,递归打印最右边的孩子。

B树中的搜索操作:
搜索类似于“二进制搜索树”中的搜索。令要搜索的密钥为k。我们从根开始,递归地向下遍历。对于每个访问的非叶子节点,如果该节点具有密钥,我们只需返回该节点即可。否则,我们递归到该节点的适当子代(该子代在第一个更大的键之前)。如果到达叶节点,但在叶节点中找不到k,则返回NULL。

逻辑:
搜索B树类似于搜索二叉树。该算法与递归相似。在每个级别,对搜索进行优化,就好像在父级范围内不存在键值,然后在另一个分支中存在键一样。由于这些值限制了搜索,因此它们也称为极限值或分离值。如果到达叶节点却找不到所需的键,则它将显示NULL。

示例:在给定的B树中搜索120。

解决方案:

在此示例中,我们可以看到,仅通过限制包含该值的键可能出现的机会,我们的搜索量就减少了。类似地,如果在上面的示例中我们必须查找180,则该控件将在步骤2停止,因为程序将发现密钥180存在于当前节点中。同样,如果要查找90,则当90 <100时,它将自动转到左侧的子树,因此控制流将类似于上述示例中所示。

C++
// C++ implemntation of search() and traverse() methods
#include
using namespace std;
 
// A BTree node
class BTreeNode
{
    int *keys;  // An array of keys
    int t;      // Minimum degree (defines the range for number of keys)
    BTreeNode **C; // An array of child pointers
    int n;     // Current number of keys
    bool leaf; // Is true when node is leaf. Otherwise false
public:
    BTreeNode(int _t, bool _leaf);   // Constructor
 
    // A function to traverse all nodes in a subtree rooted with this node
    void traverse();
 
    // A function to search a key in the subtree rooted with this node.   
    BTreeNode *search(int k);   // returns NULL if k is not present.
 
// Make the BTree friend of this so that we can access private members of this
// class in BTree functions
friend class BTree;
};
 
// A BTree
class BTree
{
    BTreeNode *root; // Pointer to root node
    int t;  // Minimum degree
public:
    // Constructor (Initializes tree as empty)
    BTree(int _t)
    {  root = NULL;  t = _t; }
 
    // function to traverse the tree
    void traverse()
    {  if (root != NULL) root->traverse(); }
 
    // function to search a key in this tree
    BTreeNode* search(int k)
    {  return (root == NULL)? NULL : root->search(k); }
};
 
// Constructor for BTreeNode class
BTreeNode::BTreeNode(int _t, bool _leaf)
{
    // Copy the given minimum degree and leaf property
    t = _t;
    leaf = _leaf;
 
    // Allocate memory for maximum number of possible keys
    // and child pointers
    keys = new int[2*t-1];
    C = new BTreeNode *[2*t];
 
    // Initialize the number of keys as 0
    n = 0;
}
 
// Function to traverse all nodes in a subtree rooted with this node
void BTreeNode::traverse()
{
    // There are n keys and n+1 children, travers through n keys
    // and first n children
    int i;
    for (i = 0; i < n; i++)
    {
        // If this is not leaf, then before printing key[i],
        // traverse the subtree rooted with child C[i].
        if (leaf == false)
            C[i]->traverse();
        cout << " " << keys[i];
    }
 
    // Print the subtree rooted with last child
    if (leaf == false)
        C[i]->traverse();
}
 
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
    // Find the first key greater than or equal to k
    int i = 0;
    while (i < n && k > keys[i])
        i++;
 
    // If the found key is equal to k, return this node
    if (keys[i] == k)
        return this;
 
    // If the key is not found here and this is a leaf node
    if (leaf == true)
        return NULL;
 
    // Go to the appropriate child
    return C[i]->search(k);
}


Java
// Java program to illustrate the sum of two numbers
 
// A BTree
class Btree {
    public BTreeNode root; // Pointer to root node
    public int t; // Minimum degree
 
    // Constructor (Initializes tree as empty)
    Btree(int t) {
        this.root = null;
        this.t = t;
    }
 
    // function to traverse the tree
    public void traverse() {
        if (this.root != null)
            this.root.traverse();
        System.out.println();
    }
 
    // function to search a key in this tree
    public BTreeNode search(int k) {
        if (this.root == null)
            return null;
        else
            return this.root.search(k);
    }
}
 
// A BTree node
class BTreeNode {
    int[] keys; // An array of keys
    int t; // Minimum degree (defines the range for number of keys)
    BTreeNode[] C; // An array of child pointers
    int n; // Current number of keys
    boolean leaf; // Is true when node is leaf. Otherwise false
 
    // Constructor
    BTreeNode(int t, boolean leaf) {
        this.t = t;
        this.leaf = leaf;
        this.keys = new int[2 * t - 1];
        this.C = new BTreeNode[2 * t];
        this.n = 0;
    }
 
    // A function to traverse all nodes in a subtree rooted with this node
    public void traverse() {
 
        // There are n keys and n+1 children, travers through n keys
        // and first n children
        int i = 0;
        for (i = 0; i < this.n; i++) {
 
            // If this is not leaf, then before printing key[i],
            // traverse the subtree rooted with child C[i].
            if (this.leaf == false) {
                C[i].traverse();
            }
            System.out.print(keys[i] + " ");
        }
 
        // Print the subtree rooted with last child
        if (leaf == false)
            C[i].traverse();
    }
 
    // A function to search a key in the subtree rooted with this node.
    BTreeNode search(int k) { // returns NULL if k is not present.
 
        // Find the first key greater than or equal to k
        int i = 0;
        while (i < n && k > keys[i])
            i++;
 
        // If the found key is equal to k, return this node
        if (keys[i] == k)
            return this;
 
        // If the key is not found here and this is a leaf node
        if (leaf == true)
            return null;
 
        // Go to the appropriate child
        return C[i].search(k);
 
    }
}


C#
// C# program to illustrate the sum of two numbers
using System;
 
// A BTree
class Btree
{
  public BTreeNode root; // Pointer to root node
  public int t; // Minimum degree
 
  // Constructor (Initializes tree as empty)
  Btree(int t)
  {
    this.root = null;
    this.t = t;
  }
 
  // function to traverse the tree
  public void traverse()
  {
    if (this.root != null)
      this.root.traverse();
    Console.WriteLine();
  }
 
  // function to search a key in this tree
  public BTreeNode search(int k)
  {
    if (this.root == null)
      return null;
    else
      return this.root.search(k);
  }
}
 
// A BTree node
class BTreeNode
{
  int[] keys; // An array of keys
  int t; // Minimum degree (defines the range for number of keys)
  BTreeNode[] C; // An array of child pointers
  int n; // Current number of keys
  bool leaf; // Is true when node is leaf. Otherwise false
 
  // Constructor
  BTreeNode(int t, bool leaf) {
    this.t = t;
    this.leaf = leaf;
    this.keys = new int[2 * t - 1];
    this.C = new BTreeNode[2 * t];
    this.n = 0;
  }
 
  // A function to traverse all nodes in a subtree rooted with this node
  public void traverse() {
 
    // There are n keys and n+1 children, travers through n keys
    // and first n children
    int i = 0;
    for (i = 0; i < this.n; i++) {
 
      // If this is not leaf, then before printing key[i],
      // traverse the subtree rooted with child C[i].
      if (this.leaf == false) {
        C[i].traverse();
      }
      Console.Write(keys[i] + " ");
    }
 
    // Print the subtree rooted with last child
    if (leaf == false)
      C[i].traverse();
  }
 
  // A function to search a key in the subtree rooted with this node.
  public BTreeNode search(int k) { // returns NULL if k is not present.
 
    // Find the first key greater than or equal to k
    int i = 0;
    while (i < n && k > keys[i])
      i++;
 
    // If the found key is equal to k, return this node
    if (keys[i] == k)
      return this;
 
    // If the key is not found here and this is a leaf node
    if (leaf == true)
      return null;
 
    // Go to the appropriate child
    return C[i].search(k);
 
  }
}
 
// This code is contributed by Rajput-Ji