Introducció de B-Tree
Les limitacions dels arbres de cerca binaris tradicionals poden ser frustrants. Coneix el B-Tree, l'estructura de dades multitalent que pot gestionar grans quantitats de dades amb facilitat. Quan es tracta d'emmagatzemar i cercar grans quantitats de dades, els arbres de cerca binaris tradicionals poden arribar a ser poc pràctics a causa del seu baix rendiment i un gran ús de memòria. Els B-Trees, també coneguts com a B-Tree o Balanced Tree, són un tipus d'arbre d'autoequilibri que es va dissenyar específicament per superar aquestes limitacions.
A diferència dels arbres de cerca binaris tradicionals, els B-Trees es caracteritzen per la gran quantitat de claus que poden emmagatzemar en un sol node, per això també es coneixen com a grans arbres de claus. Cada node d'un arbre B pot contenir diverses claus, cosa que permet que l'arbre tingui un factor de ramificació més gran i, per tant, una alçada menor. Aquesta poca alçada condueix a menys E/S de disc, el que resulta en operacions de cerca i inserció més ràpides. Els B-Trees són especialment adequats per a sistemes d'emmagatzematge que tenen accés a dades lent i voluminós, com ara discs durs, memòria flaix i CD-ROM.
B-Trees manté l'equilibri assegurant-se que cada node té un nombre mínim de claus, de manera que l'arbre sempre està equilibrat. Aquest equilibri garanteix que la complexitat del temps per a operacions com ara la inserció, la supressió i la cerca sigui sempre O(log n), independentment de la forma inicial de l'arbre.
Complexitat temporal de l'arbre B:
| Sr. No. | Algoritme | Complexitat temporal |
|---|---|---|
| 1. | Cerca | O(log n) |
| 2. | Insereix | O(log n) |
| 3. | Suprimeix | O(log n) |
Nota: n és el nombre total d'elements de l'arbre B
Propietats de B-Tree:
- Totes les fulles estan al mateix nivell.
- B-Tree es defineix pel terme grau mínim ' t ‘. El valor de ' t ' depèn de la mida del bloc de disc.
- Cada node, excepte l'arrel, ha de contenir almenys t-1 claus. L'arrel pot contenir un mínim de 1 clau.
- Tots els nodes (inclòs l'arrel) poden contenir com a màxim ( 2*t – 1 ) claus.
- El nombre de fills d'un node és igual al nombre de claus més 1 .
- Totes les claus d'un node s'ordenen en ordre creixent. El nen entre dues claus k1 i k2 conté totes les claus del rang de k1 i k2 .
- B-Tree creix i es redueix des de l'arrel, que és a diferència de Binary Search Tree. Els arbres de cerca binaris creixen cap avall i també es redueixen de cap avall.
- Com altres arbres de cerca binaris equilibrats, la complexitat de temps per cercar, inserir i eliminar és O(log n).
- La inserció d'un node a B-Tree només es fa al node de fulla.
A continuació es mostra un exemple d'un B-Tree d'ordre mínim 5
Nota: que en els B-Trees pràctics, el valor de la comanda mínima és molt més que 5.
Podem veure al diagrama anterior que tots els nodes fulla estan al mateix nivell i totes les que no són fulles no tenen un subarbre buit i tenen claus una menys que el nombre dels seus fills.
Dades interessants sobre B-Trees:
- L'alçada mínima de l'arbre B que pot existir amb n nombre de nodes i m és el nombre màxim de fills que pot tenir un node és:
![]()
- L'alçada màxima de l'arbre B que pot existir amb n nombre de nodes i t és el nombre mínim de fills que pot tenir un node no arrel és:
i
![]()
Travessia a B-Tree:
Traversal també és similar a Inorder traversal de Binary Tree. Comencem des del fill més esquerre, imprimim recursivament el fill més esquerre i, a continuació, repetim el mateix procés per als fills i les claus restants. Al final, imprimiu recursivament el fill més a la dreta.
Operació de cerca a B-Tree:
La cerca és similar a la cerca a l'arbre de cerca binari. Sigui k la clau a buscar.
- Comenceu des de l'arrel i recorreu recursivament cap avall.
- Per a cada node no full visitat,
- Si el node té la clau, simplement retornem el node.
- En cas contrari, tornem al fill adequat (el nen que està just abans de la primera clau més gran) del node.
- Si arribem a un node fulla i no trobem k al node fulla, retornem NULL.
Cercar un arbre B és similar a cercar un arbre binari. L'algorisme és similar i va amb recursivitat. A cada nivell, la cerca s'optimitza com si el valor de la clau no estigués present a l'interval del pare, llavors la clau està present en una altra branca. Com que aquests valors limiten la cerca, també es coneixen com a valors límit o valors de separació. Si arribem a un node fulla i no trobem la clau desitjada, mostrarà NULL.
Algorisme per cercar un element en un arbre B: -
C++
struct> Node {> > int> n;> > int> key[MAX_KEYS];> > Node* child[MAX_CHILDREN];> > bool> leaf;> };> Node* BtreeSearch(Node* x,> int> k) {> > int> i = 0;> > while> (i n && k>x->clau[i]) {> > i++;> > }> > if> (i n && k == x->clau [i]) {> > return> x;> > }> > if> (x->fulla) {> > return> nullptr;> > }> > return> BtreeSearch(x->fill[i], k);> }> |
C
BtreeSearch(x, k)> > i = 1> > > // n[x] means number of keys in x node> > while> i ? n[x] and k ? keyi[x]> > do> i = i + 1> > if> i n[x] and k = keyi[x]> > then> return> (x, i)> > if> leaf [x]> > then> return> NIL> > else> > return> BtreeSearch(ci[x], k)> |
Java
class> Node {> > int> n;> > int> [] key => new> int> [MAX_KEYS];> > Node[] child => new> Node[MAX_CHILDREN];> > boolean> leaf;> }> Node BtreeSearch(Node x,> int> k) {> > int> i => 0> ;> > while> (i = x.key[i]) {> > i++;> > }> > if> (i return x; } if (x.leaf) { return null; } return BtreeSearch(x.child[i], k); }> |
Python 3
class> Node:> > def> __init__(> self> ):> > self> .n> => 0> > self> .key> => [> 0> ]> *> MAX_KEYS> > self> .child> => [> None> ]> *> MAX_CHILDREN> > self> .leaf> => True> def> BtreeSearch(x, k):> > i> => 0> > while> i and k>= x.key[i]: i += 1 si i i k == x.key[i]: retorna x si x.leaf: retorna Cap retorn BtreeSearch(x.child[i], k)> |
C#
class> Node {> > public> int> n;> > public> int> [] key => new> int> [MAX_KEYS];> > public> Node[] child => new> Node[MAX_CHILDREN];> > public> bool> leaf;> }> Node BtreeSearch(Node x,> int> k) {> > int> i = 0;> > while> (i = x.key[i]) {> > i++;> > }> > if> (i return x; } if (x.leaf) { return null; } return BtreeSearch(x.child[i], k); }> |
Javascript
// Define a Node class with properties n, key, child, and leaf> class Node {> > constructor() {> > this> .n = 0;> > this> .key => new> Array(MAX_KEYS);> > this> .child => new> Array(MAX_CHILDREN);> > this> .leaf => false> ;> > }> }> // Define a function BtreeSearch that takes in a Node object x and an integer k> function> BtreeSearch(x, k) {> > let i = 0;> > while> (i = x.key[i]) {> > i++;> > }> > if> (i return x; } if (x.leaf) { return null; } return BtreeSearch(x.child[i], k); }> |
Exemples:
Entrada: Cerca 120 a l'arbre B donat.
![]()
Solució:
![]()
![]()
![]()
En aquest exemple, podem veure que la nostra cerca es va reduir només limitant les possibilitats que la clau que conté el valor pogués estar present. De la mateixa manera, si a l'exemple anterior hem de buscar 180, aleshores el control s'aturarà al pas 2 perquè el programa trobarà que la clau 180 està present dins del node actual. I de la mateixa manera, si es tracta de buscar 90, com a 90 <100, de manera que anirà automàticament al subarbre esquerre i, per tant, el flux de control anirà de la mateixa manera com es mostra a l'exemple anterior.
A continuació es mostra la implementació de l'enfocament anterior:
C++
// C++ implementation 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->travessa();> > }> > // function to search a key in this tree> > BTreeNode* search(> int> k)> > {> > return> (root == NULL) ? NULL : root->cerca (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, traverse through n> > // keys and first n children> > int> i;> > for> (i = 0; i // If this is not leaf, then before printing key[i], // traverse the subtree rooted with child C[i]. if (leaf == false) C[i]->travessa(); cout < < ' ' < < keys[i]; } // Print the subtree rooted with last child if (leaf == false) C[i]->travessa(); } // Funció per cercar la clau k en un subarbre arrelat amb aquest node BTreeNode* BTreeNode::search(int k) { // Troba la primera clau més gran o igual que k int i = 0; while (tecles i [i]) i++; // Si la clau trobada és igual a k, retorna aquest node si (claus[i] == k) retorna això; // Si la clau no es troba aquí i aquest és un node full si (fulla == true) retorna NULL; // Anar al fill adequat retorn C[i]->cerca(k); }>>> |
>
// 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, traverse>>// 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 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);>>}>}>Python 3
# Create a node>class>BTreeNode:>>def>__init__(>self>, leaf>=>False>):>>self>.leaf>=>leaf>>self>.keys>=>[]>>self>.child>=>[]># Tree>class>BTree:>>def>__init__(>self>, t):>>self>.root>=>BTreeNode(>True>)>>self>.t>=>t>># Insert node>>def>insert(>self>, k):>>root>=>self>.root>>if>len>(root.keys)>=>=>(>2>*>self>.t)>->1>:>>temp>=>BTreeNode()>>self>.root>=>temp>>temp.child.insert(>0>, root)>>self>.split_child(temp,>0>)>>self>.insert_non_full(temp, k)>>else>:>>self>.insert_non_full(root, k)>># Insert nonfull>>def>insert_non_full(>self>, x, k):>>i>=>len>(x.keys)>->1>>if>x.leaf:>>x.keys.append((>None>,>None>))>>while>i>>=>0>and>k[>0>] 0]: x.keys[i + 1] = x.keys[i] i -= 1 x.keys[i + 1] = k else: while i>= 0 i k[0] 0]: i -= 1 i += 1 si len(x.child[i].keys) == (2 * self.t) - 1: self.split_child(x, i) if k[0]> x.keys[i][0]: i += 1 self.insert_non_full(x.child[i], k) # Divideix el fill def split_child(self, x, i): t = self .t y = x.child[i] z = BTreeNode(y.leaf) x.child.insert(i + 1, z) x.keys.insert(i, y.keys[t - 1]) z.keys = y.keys[t: (2 * t) - 1] y.keys = y.keys[0: t - 1] si no y.leaf: z.child = y.child[t: 2 * t] y. fill = y.child[0: t - 1] # Imprimeix l'arbre def print_tree(self, x, l=0): print('Level ', l, ' ', len(x.keys), end=':') per i a x.keys: print(i, end=' ') print() l += 1 si len(x.child)> 0: per i a x.child: self.print_tree(i, l) # Clau de cerca a l'arbre def search_key(self, k, x=None): si x no és Cap: i = 0 mentre ix.keys[i][0]: i += 1 si i 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, traverse>>// 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 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>Javascript
// Javascript program to illustrate the sum of two numbers>// A BTree>class Btree>{>>// Constructor (Initializes tree as empty)>>constructor(t)>>{>>this>.root =>null>;>>this>.t = t;>>}>>>// function to traverse the tree>>traverse()>>{>>if>(>this>.root !=>null>)>>this>.root.traverse();>>document.write(>' '>);>>}>>>// function to search a key in this tree>>search(k)>>{>>if>(>this>.root ==>null>)>>return>null>;>>else>>return>this>.root.search(k);>>}>>}>// A BTree node>class BTreeNode>{>>// Constructor>>constructor(t,leaf)>>{>>this>.t = t;>>this>.leaf = leaf;>>this>.keys =>new>Array(2 * t - 1);>>this>.C =>new>Array(2 * t);>>this>.n = 0;>>}>>// A function to traverse all nodes in a subtree rooted with this node>>traverse()>>{>>// There are n keys and n+1 children, traverse through n keys>>// and first n children>>let 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();>>}>>document.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.>>search(k)>// returns NULL if k is not present.>>{>>>// Find the first key greater than or equal to k>>let i = 0;>>while>(i 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 patel2127>
Nota: El codi anterior no conté el programa del controlador. Cobrirem el programa complet a la nostra propera publicació Inserció B-Tree .Hi ha dues convencions per definir un arbre B, una és definir per grau mínim, la segona és definir per ordre. Hem seguit la convenció de grau mínim i seguirem la mateixa en properes publicacions a B-Tree. Els noms de variables utilitzats en el programa anterior també es mantenen iguals
Aplicacions de B-Trees:
- S'utilitza en grans bases de dades per accedir a les dades emmagatzemades al disc
- La cerca de dades en un conjunt de dades es pot aconseguir en molt menys temps amb el B-Tree
- Amb la funció d'indexació, es pot aconseguir una indexació multinivell.
- La majoria dels servidors també utilitzen l'enfocament de l'arbre B.
- Els B-Trees s'utilitzen en sistemes CAD per organitzar i cercar dades geomètriques.
- Els B-Trees també s'utilitzen en altres àrees com el processament del llenguatge natural, les xarxes informàtiques i la criptografia.
Avantatges de B-Trees:
- Els B-Trees tenen una complexitat de temps garantida d'O(log n) per a operacions bàsiques com la inserció, la supressió i la cerca, cosa que els fa adequats per a grans conjunts de dades i aplicacions en temps real.
- Els arbres B s'autoequilibren.
- Alta concurrència i alt rendiment.
- Ús eficient de l'emmagatzematge.
Desavantatges dels B-Trees:
- Els B-Trees es basen en estructures de dades basades en disc i poden tenir un ús elevat de disc.
- No és el millor per a tots els casos.
- Lent en comparació amb altres estructures de dades.
Inserció i eliminació:
Inserció B-Tree
Eliminació de l'arbre B