介绍:
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树的属性:
- 所有叶子处于同一水平。
- B树由术语最小度“ t”定义。 t的值取决于磁盘块的大小。
- 除根节点外,每个节点都必须至少包含(天花板)([t-1] / 2)个键。根目录可能至少包含1个密钥。
- 所有节点(包括根)最多可以包含t – 1个密钥。
- 节点的子代数等于该节点中的键数加1。
- 节点的所有键都按升序排序。两个键k1和k2之间的子项包含k1和k2范围内的所有键。
- B树从根开始生长和收缩,这与二叉搜索树不同。二叉搜索树向下生长,并且也从向下收缩。
- 像其他平衡二叉搜索树一样,搜索,插入和删除的时间复杂度为O(log n)。
以下是最小阶数为5的B树的示例。请注意,在实际的B树中,最小阶数的值远远大于5。
在上图中,我们可以看到所有叶节点都处于同一级别,并且所有非叶节点都没有空的子树,并且其键数小于其子节点数。
有趣的事实:
- 可以存在n个节点并且m是一个节点可以拥有的最大子节点数的B树的最小高度为:
2.可以有n个节点存在的B树的最大高度,而d是非根节点可以拥有的最小子级数目: 和
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