Vous êtes sur la page 1sur 10

Présentation de B-Abres

Introduction :
B-Tree est un arbre de recherche auto-équilibré. Dans la plupart des autres
arbres de recherche à équilibrage automatique (comme AVLet Red-Black Trees),
on suppose que tout est dans la mémoire principale. Pour comprendre
l'utilisation des B-Trees, nous devons penser à l'énorme quantité de données qui
ne peuvent pas tenir dans la mémoire principale. Lorsque le nombre de clés est
élevé, les données sont lues à partir du disque sous forme de blocs. Le temps
d'accès au disque est très élevé par rapport au temps d'accès à la mémoire
principale. L'idée principale de l'utilisation de B-Trees est de réduire le nombre
d'accès au disque. La plupart des opérations sur l'arbre (recherche, insertion,
suppression, max, min, ..etc ) nécessitent des accès disque O(h) où h est la
hauteur de l'arbre. L'arbre B est un gros arbre. La hauteur des B-Trees est
maintenue basse en mettant le maximum de clés possibles dans un nœud B-
Tree. En règle générale, la taille du nœud B-Tree est maintenue égale à la taille du
bloc de disque.
Complexité temporelle de B-Abres :

Propriétés de B-Abres :

1. Toutes les feuilles sont au même niveau.


2. Un B-Abres est défini par le terme degré minimum « t ». La valeur de t
dépend de la taille du bloc de disque.
3. Chaque nœud, à l'exception de la racine, doit contenir au moins t-1
clés. La racine peut contenir au moins 1 clé.
4. Tous les nœuds (y compris la racine) peuvent contenir au plus 2*t – 1
clés.
5. Le nombre d'enfants d'un nœud est égal au nombre de clés qu'il
contient plus 1.
6. Toutes les clés d'un nœud sont triées par
7. ordre croissant. L'enfant entre deux clés k1 et k2 contient toutes les clés
dans la plage de k1 et k2.
8. B-Abres grandit et rétrécit à partir de la racine, ce qui est différent de
l'arbre de recherche binaire. Les arbres de recherche binaire poussent
vers le bas et diminuent également de bas en haut.
9. Comme d'autres arbres de recherche binaire équilibrés, la complexité
temporelle de la recherche, de l'insertion et de la suppression est de O
(log n).
10. L'insertion d'un nœud dans B-Abres se produit uniquement au nœud
feuille.
Voici un exemple de B-Abres de commande minimum 5. Notez que dans les B-
Abres pratiques, la valeur de la commande minimum est bien supérieure à 5.
Nous pouvons voir dans le diagramme ci-dessus que tous les nœuds feuilles sont
au même niveau et que tous les nœuds non-feuilles n'ont pas de sous-arbre vide
et ont des clés un de moins que le nombre de leurs enfants.
Faits intéressants:
1. La hauteur minimale du B-Abres qui peut exister avec n nombre de
nœuds et m est le nombre maximal d'enfants d'un nœud peut avoir
est :
2. La hauteur maximale du B-Abres qui peut exister avec n nombre de
nœuds et t est le nombre minimum d'enfants qu'un nœud non racine

peut avoir est : et


Traversée dans B-Abres :
la traversée est également similaire à la traversée dans l'ordre de l'arbre
binaire. Nous commençons par l'enfant le plus à gauche, imprimons
récursivement l'enfant le plus à gauche, puis répétons le même processus pour
les enfants et les clés restants. À la fin, imprimez récursivement l'enfant le plus à
droite.

Opération de recherche dans B-Tree : La


recherche est similaire à la recherche dans l'arbre de recherche binaire. Soit k la
clé à rechercher. Nous partons de la racine et parcourons récursivement vers le
bas. Pour chaque nœud non-feuille visité, si le nœud a la clé, nous renvoyons
simplement le nœud. Sinon, nous revenons à l'enfant approprié (l'enfant qui est
juste avant la première plus grande clé) du nœud. Si nous atteignons un nœud
feuille et ne trouvons pas k dans le nœud feuille, nous renvoyons NULL.
Logique : La
recherche d'un B-Tree est similaire à la recherche d'un arbre
binaire. L'algorithme est similaire et va de pair avec la récursivité. A chaque
niveau, la recherche est optimisée comme si la valeur de la clé n'était pas
présente dans la plage du parent alors la clé est présente dans une autre
branche. Comme ces valeurs limitent la recherche, elles sont également appelées
valeur limite ou valeur de séparation. Si nous atteignons un nœud feuille et ne
trouvons pas la clé souhaitée, il affichera NULL.
Exemple : Recherche de 120 dans le B-Tree donné.

Solution:
Dans cet exemple, nous pouvons voir que notre recherche a été réduite en
limitant simplement les chances où la clé contenant la valeur pourrait être
présente. De même, si dans l'exemple ci-dessus, nous devons rechercher 180, le
contrôle s'arrêtera à l'étape 2 car le programme trouvera que la clé 180 est
présente dans le nœud actuel. Et de la même manière, s'il s'agit de rechercher 90,
alors en tant que 90 < 100, il ira automatiquement au sous-arbre de gauche et le
flux de contrôle ira donc de la même manière que celui illustré dans l'exemple ci-
dessus.

Le code ci-dessus ne contient pas le programme pilote. Nous couvrirons le


programme complet dans notre prochain article sur B-Tree Insertion .
Il existe deux conventions pour définir un B-Tree, la première consiste à définir
par degré minimum (suivi dans le livre de Cormen ), la seconde est définie par
ordre. Nous avons suivi la convention du diplôme minimum et nous suivrons la
même chose dans les prochains articles sur B-Tree. Les noms de variables utilisés
dans le programme ci-dessus sont également conservés comme dans le livre
Cormen pour une meilleure lisibilité.
Insertion et suppression
B-Tree Insertion à ce que nous atteignions un nœud feuille. Une fois que nous
atteignons un nœud feuille, nous insérons la clé dans ce nœud
feuille. Contrairement aux BST, nous avons une plage prédéfinie sur le nombre de
clés qu'un nœud peut contenir. Ainsi, av
ant d'insérer une clé dans le nœud, nous

Insérer une opération dans B-Abres


l'opération insertion est discutée. Une nouvelle clé est toujours insérée au nœud
feuille. Que la clé à insérer soit k. Comme ABR, nous partons de la racine et
descendons jusqu'à ce que nous atteignions un nœud feuille. Une fois que nous
atteignons un nœud feuille, nous insérons la clé dans ce nœud
feuille. Contrairement aux ABR, nous avons une plage prédéfinie sur le nombre de
clés qu'un nœud peut contenir. Ainsi, avant d'insérer une clé dans le nœud, nous
nous assurons que le nœud dispose d'un espace supplémentaire.
Comment s'assurer qu'un nœud a de l'espace disponible pour une clé avant que la
clé ne soit insérée ? Nous utilisons une opération appelée splitChild() qui est
utilisée pour diviser un enfant d'un nœud. Voir le diagramme suivant pour
comprendre la division. Dans le diagramme suivant, l'enfant y de x est divisé en
deux nœuds y et z. Notez que l'opération splitChild déplace une clé vers le haut et
c'est la raison pour laquelle les B-Abres grandissent, contrairement aux ABR qui
poussent vers le bas.
Attention lecteur ! N'arrêtez pas d'apprendre maintenant. Obtenez tous les
concepts importants de DSA avec le

Comme discuté ci-dessus, pour insérer une nouvelle clé, nous descendons de la
racine à la feuille. Avant de descendre jusqu'à un nœud, nous vérifions d'abord si
le nœud est plein. Si le nœud est plein, nous le divisons pour créer de
l'espace. Voici l'algorithme complet.
Insertion
1) Initialisez x en tant que root.
2) Tant que x n'est pas une feuille, procédez comme suit
.. a) Trouvez l'enfant de x qui va être traversé ensuite. Que l'enfant soit y.
.. b) Si y n'est pas plein, changez x pour pointer vers y.
.. c) Si y est plein, divisez-le et changez x pour pointer vers l'une des deux parties
de y. Si k est plus petit que la clé médiane dans y, alors définissez x comme
première partie de y. Sinon deuxième partie de y. Lorsque nous divisons y, nous
déplaçons une clé de y vers son parent x.
3) La boucle de l'étape 2 s'arrête lorsque x est une feuille. x doit avoir de l'espace
pour 1 clé supplémentaire car nous avons divisé tous les nœuds à
l'avance. Insérez donc simplement k dans x.
Notez que l'algorithme suit le livre de Cormen. Il s'agit en fait d'un algorithme
d'insertion proactif où avant de descendre sur un nœud, on le divise s'il est
plein. L'avantage de diviser avant est que nous ne parcourons jamais un nœud
deux fois. Si nous ne divisons pas un nœud avant d'y descendre et ne le divisons
que si une nouvelle clé est insérée (réactive), nous pouvons finir par traverser à
nouveau tous les nœuds de la feuille à la racine. Cela se produit dans les cas où
tous les nœuds sur le chemin de la racine à la feuille sont pleins. Ainsi, lorsque
nous arrivons au nœud feuille, nous le divisons et déplaçons une clé vers le
haut. Déplacer une clé vers le haut entraînera une division du nœud parent (car le
parent était déjà plein). Cet effet en cascade ne se produit jamais dans cet
algorithme d'insertion proactif. Il y a cependant un inconvénient à cette insertion
proactive, nous pouvons faire des scissions inutiles.

Comprenons l'algorithme avec un exemple d'arbre de degré minimum 't' égal à 3


et une séquence d'entiers 10, 20, 30, 40, 50, 60, 70, 80 et 90 dans un B-Tree
initialement vide.
Initialement, la racine est NULL. Insérons d'abord 10.

Insérons maintenant 20, 30, 40 et 50. Ils seront tous insérés dans la racine car le
nombre maximum de clés qu'un nœud peut accueillir est de 2*t - 1 qui est 5.

Insérons maintenant 60. Puisque le nœud racine est plein, il sera d'abord divisé
en deux, puis 60 sera inséré dans l'enfant approprié.
Insérons maintenant 70 et 80. Ces nouvelles clés seront insérées dans la feuille
appropriée sans aucune division.

Insérons maintenant 90. Cette insertion provoquera une scission. La touche du


milieu ira jusqu'au parent.

Supprimer l'opération dans B-Abres


Processus de suppression :
La suppression d'un arbre B est plus compliquée que l'insertion, car nous
pouvons supprimer une clé de n'importe quel nœud, pas seulement une feuille, et
lorsque nous supprimons une clé d'un nœud interne, nous devrons réorganiser
les enfants du nœud.
Comme pour l'insertion, nous devons nous assurer que la suppression ne viole
pas les propriétés du B-tree . Tout comme nous devions nous assurer qu'un nœud
ne devenait pas trop gros à cause de l'insertion, nous devons nous assurer qu'un
nœud ne devienne pas trop petit lors de la suppression (sauf que la racine est
autorisée à avoir moins que le nombre minimum t-1 des clés). Tout comme un
simple algorithme d'insertion pourrait devoir sauvegarder si un nœud sur le
chemin vers lequel la clé devait être insérée était plein, une approche simple de
suppression pourrait devoir sauvegarder si un nœud (autre que la racine) le long
du chemin où la clé doit être supprimée a le nombre minimum de clés.
La procédure de suppression supprime la clé k du sous-arbre dont la racine est
x. Cette procédure garantit que chaque fois qu'elle s'appelle récursivement sur un
nœud x, le nombre de clés dans x est au moins le degré minimum t . Notez que
cette condition nécessite une clé de plus que le minimum requis par les
conditions habituelles de l'arbre B, de sorte qu'il peut parfois être nécessaire de
déplacer une clé dans un nœud enfant avant que la récursivité ne descende vers
cet enfant. Cette condition renforcée nous permet de supprimer une clé de l'arbre
en un seul passage vers le bas sans avoir à « sauvegarder » (à une exception près,
que nous expliquerons). Vous devez interpréter la spécification suivante pour la
suppression d'un arbre B en sachant que si le nœud racine x devient un nœud
interne n'ayant pas de clés (cette situation peut se produire dans les cas 2c et 3b,
alors nous supprimons x, et le seul enfant de x x .
Nous esquissons le fonctionnement de la suppression avec divers cas de
suppression de clés d'un arbre B.
1. Si la clé k est dans le nœud x et que x est une feuille, supprimez la clé k de x.
2. Si la clé k se trouve dans le nœud x et que x est un nœud interne, procédez
comme suit.
a) Si l'enfant y qui précède k dans le nœud x a au moins t clés, alors trouvez le
prédécesseur k0 de k dans le sous-arbre enraciné en y. Supprimez récursivement
k0 et remplacez k par k0 dans x. (Nous pouvons trouver k0 et le supprimer en un
seul passage vers le bas.)

b) Si y a moins de t clés, alors, symétriquement, examinez l'enfant z qui suit k


dans le nœud x. Si z a au moins t clés, alors trouvez le successeur k0 de k dans le
sous-arbre enraciné en z. Supprimez récursivement k0 et remplacez k par k0
dans x. (Nous pouvons trouver k0 et le supprimer en un seul passage vers le bas.)
c) Sinon, si à la fois y et z n'ont que t-1 clés, fusionnez k et tout z en y, de sorte que
x perd à la fois k et le pointeur vers z, et y contient maintenant 2t-1 clés. Libérez
ensuite z et supprimez récursivement k de y.
3. Si la clé k n'est pas présente dans le nœud interne x, déterminez la racine xc(i)
du sous-arbre approprié qui doit contenir k, si k est présent dans l'arbre. Si xc(i)
n'a que t-1 clés, exécutez l'étape 3a ou 3b si nécessaire pour garantir que nous
descendons à un nœud contenant au moins t clés. Terminez ensuite en récursif
sur le fils approprié de x.
a) Si xc(i) n'a que t-1 clés mais a un frère immédiat avec au moins t clés, donnez
à xc(i) une clé supplémentaire en déplaçant une clé de x vers le bas dans xc(i), en
déplaçant une clé de xc (i) le frère gauche ou droit immédiat de 's up dans x, et
déplacer le pointeur enfant approprié du frère dans xc(i).
b) Si xc(i) et les deux frères immédiats de xc(i) ont des clés t-1, fusionnez xc(i)
avec un frère, ce qui implique de déplacer une clé de x vers le bas dans le nouveau
nœud fusionné pour devenir la médiane clé pour ce nœud.
Étant donné que la plupart des clés d'un arbre B se trouvent dans les feuilles, les
opérations de suppression sont le plus souvent utilisées pour supprimer les clés
des feuilles. La procédure de suppression récursive agit alors en un seul passage
descendant dans l'arbre, sans avoir à effectuer de sauvegarde. Cependant, lors de
la suppression d'une clé dans un nœud interne, la procédure effectue un passage
descendant dans l'arbre mais peut devoir revenir au nœud d'où la clé a été
supprimée pour remplacer la clé par son prédécesseur ou son successeur (cas 2a
et 2b).
Les figures suivantes expliquent le processus de suppression.

Vous aimerez peut-être aussi