Remove ads
structure de données De Wikipédia, l'encyclopédie libre
En informatique, un arbre B (appelé aussi B-arbre par analogie au terme anglais « B-tree ») est une structure de données en arbre équilibré. Les arbres B sont principalement mis en œuvre dans les mécanismes de gestion de bases de données et de systèmes de fichiers. Ils stockent les données sous une forme triée et permettent une exécution des opérations d'insertion et de suppression en temps toujours logarithmique.
Découvreurs ou inventeurs | |
---|---|
Date de découverte | |
Problème lié | |
Structure des données |
Pire cas |
, , |
---|---|
Moyenne |
, , |
Pire cas | |
---|---|
Moyenne |
Le principe est de permettre aux nœuds parents de posséder plus de deux nœuds enfants : c'est une généralisation de l’arbre binaire de recherche. Ce principe minimise la taille de l'arbre et réduit le nombre d'opérations d'équilibrage. De plus un arbre B grandit à partir de la racine, contrairement à un arbre binaire de recherche qui croît à partir des feuilles.
Le créateur des arbres B, Rudolf Bayer, n'a pas explicité la signification du « B ». L'explication la plus fréquente est que le B correspond au terme anglais « balanced » (en français : « équilibré »). Cependant, il pourrait aussi découler de « Bayer », du nom du créateur, ou de « Boeing », du nom de la firme pour laquelle le créateur travaillait (Boeing Scientific Research Labs).
Les arbres B ont été inventés en 1970 par Rudolf Bayer et Edward M.McCreight dans les laboratoires de recherche de Boeing. Le but était de pouvoir gérer les pages d'index de fichiers de données, en tenant compte du fait que le volume des index pouvait être si grand que seule une fraction des pages pouvait être chargée en mémoire vive. Le premier article[2] décrivant le mécanisme des arbres B a été écrit en juillet et publié en .
Un arbre étiqueté est un arbre (au sens informatique du terme) tel qu'à chaque nœud on associe une étiquette ou clé (ou bien plusieurs étiquettes ou clés dans le cas des arbres B) prise(s) dans un ensemble donné. Donc formellement un arbre étiqueté est un couple formé d'un graphe orienté, acyclique et faiblement connexe et d'une fonction d'étiquetage des arbres qui attribue à chaque nœud une étiquette ou une clé. Parmi les arbres étiquetés, un arbre B possède quelques propriétés spécifiques supplémentaires.
Soient L et U deux entiers naturels non nuls tels que L ≤ U. En toute généralité, on définit alors un L-U arbre B[3] de la manière suivante : chaque nœud, sauf la racine, possède un minimum de L−1 clés (appelées aussi éléments), un maximum de U−1 clés et au plus U fils[4]. Pour chaque nœud interne — nœud qui n’est pas une feuille —, le nombre de fils est toujours égal au nombre de clés augmenté d’une unité. Si n est le nombre de fils, alors on parle de n-nœud. Un L-U arbre ne contient que des n-nœuds avec L ≤ n ≤ U. Souvent on choisit la configuration L = t et U = 2 × t : t est appelé le degré minimal de l’arbre B.
De plus, la construction des arbres B garantit qu’un arbre B est toujours équilibré. Chaque clé d’un nœud interne est en fait une borne qui distingue les sous-arbres de ce nœud. Par exemple, si un nœud a 3 fils — lesquels constituent les racines respectives de trois sous-arbres : sous-arbre gauche, sous-arbre du milieu et sous-arbre droit —, alors il a 2 clés notées c1 et c2 qui délimitent les clés de chaque sous-arbre : les clés du sous-arbre gauche seront inférieures à c1 ; les clés du sous-arbre du milieu seront comprises entre c1 et c2 ; les clés du sous-arbre droit seront supérieures à c2.
Un arbre B est implémenté par un arbre enraciné[5]. Un nœud est étiqueté par :
De plus, un arbre B vérifie ces propriétés :
template<typename T, size_t U>
struct Noeud {
size_t n; // nombre de clés utilisées
bool feuille; // si ce nœud est une feuille
Noeud<T, U>* parent = nullptr; // connaître le parent peut être nécessaire dans certains algorithmes
T cles[U-1]; // tableau des clés
Noeud<T, U>* branches[U]; // tableau des branches, si ce n'est pas une feuille
};
La plupart du temps, la configuration est telle que U = 2 L. On parle alors d’arbre B d'ordre L.
Un arbre B d’ordre t est alors défini plus simplement par un arbre qui satisfait les propriétés suivantes :
Comme on le verra par la suite, la hauteur d'un B-arbre est logarithmique en le nombre d'éléments. Ainsi, les opérations de recherche, insertion et suppression sont implémentables en O(log n) dans le pire cas, où n est le nombre d'éléments.
La recherche est effectuée de la même manière que dans un arbre binaire de recherche. Partant de la racine, on parcourt récursivement l’arbre ; à chaque nœud, on choisit le sous-arbre fils dont les clés sont comprises entre les mêmes bornes que celles de la clé recherchée grâce à une recherche dichotomique.
fonction Rechercher(noeud, x):
i = 0
tant que i < noeud.taille et x > noeud.cles[i]:
i += 1
si noeud.feuille:
retourner i < noeud.taille et x == noeud.cles[i]
sinon:
si i < noeud.taille et x == noeud.cles[i]:
retourner Vrai
sinon:
retourner Rechercher(noeud.branches[i], x)
Dans de nombreuses implémentations, l'égalité () entre éléments est remplacée par l'équivalence (). Il faut donc veiller à utiliser des types de données où deux éléments équivalents sont considérés comme égaux.
L’insertion nécessite tout d’abord de chercher le nœud où la nouvelle clé devrait être insérée, et l’insérer. La suite se déroule récursivement, selon qu’un nœud ait ou non trop de clés : s’il possède un nombre acceptable de clés, on ne fait rien ; autrement on le transforme en deux nœuds, chacun possédant un nombre minimum de clés, puis on fait « remonter » la clé du milieu qui est alors insérée dans le nœud père. Ce dernier peut du coup se retrouver avec un nombre excessif de fils ; le procédé se poursuit ainsi jusqu’à ce que l’on atteigne la racine. Si celle-ci doit être divisée, on fait « remonter » la clé du milieu dans une nouvelle racine, laquelle génèrera comme nœuds fils les deux nœuds créés à partir de l’ancienne racine, à l’instar de l'étape précédente. Pour que l’opération soit possible, on remarque qu’il faut que U ≥ 2 L ; sinon les nouveaux nœuds ne possèderont pas suffisamment de clés.
Une variante consiste à éclater préventivement chaque nœud « plein » (possédant le nombre maximal de clés) rencontré lors de la recherche du nœud où se réalisera l'insertion. De cette manière on évite une remontée dans l'arbre, puisque l'on assure que le père d'un nœud à scinder en deux peut accueillir une clé supplémentaire. La contrepartie en est une légère augmentation de la hauteur moyenne de l'arbre.
fonction Inserer(x,c)
n = nombre de clefs du noeud x
Soit i tel que x.clef[i] > c ou i >= n
Si x est une feuille :
Inserer c dans x.clef a la i-ieme place
Sinon:
Si x.fils[i] est complet:
Scinder x.fils[i]
Si c > x.clef[i]:
i := i+1
FinSi
FinSi
Inserer(x.fils[i],c)
FinSi
FinFonction
On doit d’abord chercher la clé à supprimer et la supprimer du nœud qui la contient.
Notamment après une suppression, l'arbre peut être rééquilibré. Cette opération consiste à répartir équitablement les valeurs dans les différents nœuds de l'arbre et à rétablir les propriétés de remplissage minimum des nœuds.
Le rééquilibrage commence au niveau des feuilles et progresse vers la racine, jusqu'à celle-ci. La redistribution consiste à transférer un élément d'un nœud voisin qui possède suffisamment de valeurs vers le nœud qui en manque. Cette redistribution est appelée rotation. Si aucun voisin ne peut fournir de valeur sans être lui même sous la limite, le nœud déficient doit être fusionné avec un voisin. Cette opération provoque la perte d'un séparateur dans le nœud parent, celui-ci peut alors être en déficit et a besoin d'être équilibré. La fusion et redistribution se propage jusqu'à la racine, seul élément où la déficience en valeurs est tolérée.
Un algorithme d'équilibrage simple consiste à:
La rotation à gauche d'un cran entre deux nœuds voisins se fait en
Ce genre d'opération peut être également utilisé pour compresser l'arbre: un arbre destiné à la lecture seule peut être vidé d'un maximum de cases mémoires inutilisées en remplissant au maximum un minimum de nœuds.
Soit le nombre de clefs que contient l’arbre B. La hauteur de l’arbre vérifie l’inégalité :
L’arbre Arbre B+ (en) diffère légèrement de l’arbre B, en ceci que toutes les données sont stockées exclusivement dans des feuilles, et celles-ci sont reliées entre elles.
D’autres variantes existent également, telles que l’arbre B* (en) — pour lequel on exige que le taux de remplissage minimal des nœuds internes soit de 2/3 — ou l’arbre B*+ (en) (qui combine les arbres B+ et B*).
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.