Menu
Coddy logo textTech

Arbre AVL

Dernière mise à jour

Un arbre AVL est un arbre binaire de recherche auto-équilibré. Il fonctionne comme un ABR normal, mais après chaque insertion il vérifie le facteur d'équilibre de chaque ancêtre - la différence de hauteur entre ses sous-arbres gauche et droit - et si un nœud devient déséquilibré (une différence supérieure à 1), il effectue des rotations pour rétablir l'équilibre. Appuyez sur lecture ci-dessus pour voir les valeurs insérées et l'arbre pivoter pour retrouver sa forme.

Comme il ne laisse jamais l'arbre pencher plus que légèrement, un arbre AVL garantit une hauteur en O(log n), de sorte que la recherche, l'insertion et la suppression sont toujours en O(log n) - même pour une entrée triée qui ruinerait un ABR ordinaire. Le coût réside dans les rotations supplémentaires et la tenue des hauteurs à chaque insertion.

Complexité en temps et en espace

OpérationComplexitéNotes
RechercheO(log n)La hauteur est toujours ~1.44 log n
InsertionO(log n)Plus O(1) rotations
SuppressionO(log n)Plus O(log n) rotations
EspaceO(n)Un champ de hauteur par nœud

Les quatre cas de rotation

CasDéséquilibreCorrection
Gauche-GaucheLourd sur la gauche de l'enfant gaucheUne rotation à droite
Droite-DroiteLourd sur la droite de l'enfant droitUne rotation à gauche
Gauche-DroiteLourd sur la droite de l'enfant gaucheRotation à gauche puis à droite
Droite-GaucheLourd sur la gauche de l'enfant droitRotation à droite puis à gauche

Exemple résolu

Insertion de [10, 20, 30, 40, 50, 25] une valeur à la fois :

ÉtapeStructureAction
Insérer 1010Le premier nœud devient la racine ; équilibré
Insérer 2010(_, 20)Va à droite de 10 ; toujours équilibré
Insérer 3020(10, 30)Droite-Droite en 10, donc une rotation à gauche hisse 20 à la racine
Insérer 4020(10, 30(_, 40))Va à droite de 30 ; tous les facteurs d'équilibre restent dans ±1
Insérer 5020(10, 40(30, 50))Droite-Droite en 30, donc une rotation à gauche en 30 hisse 40
Insérer 2530(20(10, 25), 40(_, 50))Droite-Gauche en 20 : rotation à droite du sous-arbre de 40, puis rotation à gauche de 20

Quand utiliser un arbre AVL

À utiliser quandÀ éviter quand
Les recherches dépassent largement les insertions et vous voulez la hauteur la plus compacte possibleLes insertions et suppressions dominent - les rotations et le rééquilibrage supplémentaires coûtent plus qu'un arbre rouge-noir
Vous avez besoin d'un pire cas garanti en O(log n), même pour une entrée adverse ou triéeUne simple table de hachage suffirait - vous n'avez pas besoin de parcours ordonné ni de requêtes par plage
Vous avez besoin d'opérations ordonnées : parcours en ordre, prédécesseur/successeur, requêtes par plageLe jeu de données est minuscule - un ABR simple ou un tableau trié est plus simple et assez rapide
Les données peuvent arriver déjà triées, ce qui transformerait un ABR non équilibré en liste chaînéeVous ne pouvez pas vous permettre la mémoire supplémentaire du champ de hauteur par nœud dans un espace très restreint

Code de AVL Tree

Une implémentation propre et exécutable de AVL Tree en Python, JavaScript, Java, C++, C. Choisissez un langage, copiez le code ou ouvrez-le préchargé dans le Playground Coddy.

Code de AVL Tree en Python

Python
1class Node:2    def __init__(self, key):3        self.key = key4        self.left = None5        self.right = None6        self.height = 17
8
9def height(node):10    return node.height if node else 011
12
13def update(node):14    node.height = 1 + max(height(node.left), height(node.right))15
16
17def rotate_right(y):18    x = y.left19    y.left = x.right20    x.right = y21    update(y)22    update(x)23    return x24
25
26def rotate_left(x):27    y = x.right28    x.right = y.left29    y.left = x30    update(x)31    update(y)32    return y33
34
35def insert(node, key):36    if node is None:37        return Node(key)38    if key < node.key:39        node.left = insert(node.left, key)40    else:41        node.right = insert(node.right, key)42    update(node)43    balance = height(node.left) - height(node.right)44    # Four imbalance cases: LL, RR, LR, RL45    if balance > 1 and key < node.left.key:46        return rotate_right(node)47    if balance < -1 and key > node.right.key:48        return rotate_left(node)49    if balance > 1:50        node.left = rotate_left(node.left)51        return rotate_right(node)52    if balance < -1:53        node.right = rotate_right(node.right)54        return rotate_left(node)55    return node56
57
58def inorder(node):59    if node is None:60        return []61    return inorder(node.left) + [node.key] + inorder(node.right)62
63
64root = None65for key in [10, 20, 30, 40, 50, 25]:66    root = insert(root, key)67
68print("Inorder:", inorder(root))69print("Root:", root.key, "| tree height:", root.height)
Exécutez ce code dans le Playground Python

FAQ sur l'arbre AVL

Qu'est-ce qu'un facteur d'équilibre dans un arbre AVL ?
Le facteur d'équilibre d'un nœud est la hauteur de son sous-arbre gauche moins la hauteur de son sous-arbre droit. Un arbre AVL maintient le facteur d'équilibre de chaque nœud à -1, 0 ou +1 ; si une insertion le pousse hors de cette plage, une rotation rétablit l'équilibre.
Quelle est la différence entre un arbre AVL et un arbre rouge-noir ?
Les deux sont des ABR auto-équilibrés avec des opérations en O(log n). Les arbres AVL sont plus strictement équilibrés, donc les recherches sont légèrement plus rapides, mais ils peuvent faire plus de rotations à l'insertion/suppression. Les arbres rouge-noir sont plus lâchement équilibrés, favorisant moins de rotations - c'est pourquoi de nombreuses bibliothèques standard les utilisent pour les maps et les ensembles.
Pourquoi utiliser un arbre AVL plutôt qu'un arbre binaire de recherche ordinaire ?
Un ABR ordinaire peut se dégrader en opérations O(n) si les valeurs arrivent triées, formant une chaîne déséquilibrée. Un arbre AVL pivote pour rester équilibré, garantissant une hauteur et des opérations en O(log n) quel que soit l'ordre d'insertion.
Un arbre AVL est-il meilleur qu'un arbre rouge-noir pour un index de base de données ?
Cela dépend de la charge de travail. Les arbres AVL sont plus rigidement équilibrés, ils gagnent donc quand les lectures dominent et que vous voulez les chemins de recherche les plus courts possibles. Mais la plupart des bases de données et bibliothèques de langages choisissent des arbres rouge-noir (ou des arbres B) car ils se rééquilibrent avec moins de rotations sur des charges à forte écriture, ce qui compte davantage quand les insertions et suppressions sont fréquentes.
Combien de rotations une seule insertion AVL nécessite-t-elle ?
Au plus une rotation - simple ou double (en deux étapes) - est nécessaire pour rééquilibrer l'arbre après l'insertion d'une valeur. En effet, une insertion augmente la hauteur d'un sous-arbre d'au plus un, donc une seule correction au niveau de l'ancêtre déséquilibré le plus bas suffit. La suppression est différente : elle peut nécessiter jusqu'à O(log n) rotations à mesure que le rééquilibrage se propage vers la racine.
Dois-je mettre à jour les hauteurs des nœuds après chaque rotation ?
Oui - une erreur courante consiste à faire pivoter correctement les pointeurs mais à oublier de recalculer la hauteur des deux nœuds concernés. Après chaque rotation, vous devez d'abord mettre à jour la hauteur du nœud rétrogradé puis celle du nœud promu, car la hauteur du nœud promu dépend de ses nouveaux enfants. Omettre cela laisse des facteurs d'équilibre obsolètes qui faussent les décisions de rééquilibrage futures.
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER