--- title: "Tri par tas et arbres AVL" date: "2022-03-16" patat: eval: tai: command: fish fragment: false replace: true ccc: command: fish fragment: false replace: true images: backend: auto --- # Questions sur les notions du dernier cours * Qu'est-ce qu'un arbre AVL? . . . * Un arbre binaire qui a la propriété suivante: * La différence de hauteur de chaque noeud est d'au plus 1. * Tous les noeuds ont `fe = hd - hg = {-1, 0, 1}`. * Pourquoi utiliser un arbre AVL plutôt qu'un arbre binaire de recherche? . . . * Insertion/recherche/... toujours en $O(\log_2(N))$. # AVL ou pas? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((21))-->id1((9)); id0-->id2((40)); id1-->id3((5)); id1-->id4((10)); id3-->id5((3)); id3-->id6((7)) id6-->id7((6)) id6-->id8(( )) id2-->id9((33)) id2-->id10((61)) id9-->id11((22)) id9-->id12((39)) id10-->id13(( )) id10-->id14((81)) style id8 fill:#fff,stroke:#fff style id13 fill:#fff,stroke:#fff ``` . . . * Ajouter un noeud pour qu'il le soit plus. # Insertion dans un arbre AVL (1/N) 1. On part d'un arbre AVL. 2. On insère un nouvel élément. ::: columns :::: column * `hd ? hg`. * Insertion de `4`? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); ``` :::: :::: column . . . * `hd = hg` ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); id1-->id4(( )); id1-->id5((4)); style id4 fill:#fff,stroke:#fff ``` * `fe = -1` :::: ::: # Insertion dans un arbre AVL (2/N) 1. On part d'un arbre AVL. 2. On insère un nouvel élément. ::: columns :::: column * `hd ? hg`. * Insertion de `4`? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); id2-->id3((18)); id2-->id4(( )); style id4 fill:#fff,stroke:#fff ``` :::: :::: column . . . * `hd < hg` ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); id2-->id3((18)); id2-->id4(( )); id1-->id5(( )); id1-->id6((4)); style id4 fill:#fff,stroke:#fff style id5 fill:#fff,stroke:#fff ``` * `fe = 0` :::: ::: # Insertion dans un arbre AVL (3/N) 1. On part d'un arbre AVL. 2. On insère un nouvel élément. ::: columns :::: column * `hd ? hg`. * Insertion de `4`? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); id1-->id3(( )); id1-->id4((6)); id2-->id5(( )); id2-->id6(( )); style id3 fill:#fff,stroke:#fff style id5 fill:#fff,stroke:#fff style id6 fill:#fff,stroke:#fff ``` :::: :::: column . . . * `hd > hg` ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((12))-->id1((1)); id0-->id2((19)); id1-->id3(( )); id1-->id4((6)); id4-->id5((4)); id4-->id6(( )); id2-->id7(( )); id2-->id8(( )); style id3 fill:#fff,stroke:#fff style id6 fill:#fff,stroke:#fff style id7 fill:#fff,stroke:#fff style id8 fill:#fff,stroke:#fff ``` :::: ::: **Déséquilibre!** Que vaut `fe`? . . . * `fe = 2` # Les cas de déséquilibre ::: columns :::: column ## Cas 1a * `u`, `v`, `w` même hauteur. * déséquilibre en `B` après insertion dans `u`  :::: :::: column ## Cas 1a * Comment rééquilibrer? . . . * ramène `u`, `v` `w` à la même hauteur. * `v` à droite de `A` (gauche de `B`)  :::: ::: # Les cas de déséquilibre ::: columns :::: column ## Cas 1b (symétrique 1a)  :::: :::: column ## Cas 1b (symétrique 1a) * Comment rééquilibrer? . . .  :::: ::: # Les cas de déséquilibre ::: columns :::: column ## Cas 2a * `v1`, `v2`, `u`, `w` même hauteur. * déséquilibre en `C` après insertion dans `v2`  :::: :::: column ## Cas 2a * Comment rééquilibrer? . . . * ramène `u`, `v1`, `v2`, `w` à la même hauteur. * `v2` à droite de `B` (gauche de `C`) * `B` à droite de `A` (gauche de `C`) * `v1` à droite de `A` (gauche de `B`)  :::: ::: # Les cas de déséquilibre ::: columns :::: column ## Cas 2b (symétrique 2a)  :::: :::: column ## Cas 2b (symétrique 2a) * Comment rééquilibrer? . . .  :::: ::: # Le facteur d'équilibre (balance factor) ## Définition ``` fe(arbre) = hauteur(droite(arbre)) - hauteur(gauche(arbre)) ``` ## Valeurs possibles? . . . ``` fe = {-1, 0, 1} // arbre AVL fe = {-2, 2} // arbre déséquilibré ``` {width=40%} # Algorithme d'insertion * Insérer le noeud comme d'habitude. * Mettre à jour les facteurs d'équilibre jusqu'à la racine (ou au premier noeud déséquilibré). * Rééquilibrer le noeud si nécessaire. ## Cas possibles ::: columns :::: column ## Sous-arbre gauche (avant) ``` fe(P) = 1 fe(P) = 0 fe(P) = -1 ``` :::: :::: column ## Sous-arbre gauche (après) . . . ``` => fe(P) = 0 => fe(P) = -1 => fe(P) = -2 // Rééquilibrer P ``` :::: ::: # Algorithme d'insertion * Insérer le noeud comme d'habitude. * Mettre à jour les facteurs d'équilibre jusqu'à la racine (ou au premier noeud déséquilibré). * Rééquilibrer le noeud si nécessaire. ## Cas possibles ::: columns :::: column ## Sous-arbre droit (avant) ``` fe(P) = 1 fe(P) = 0 fe(P) = -1 ``` :::: :::: column ## Sous-arbre droit (après) . . . ``` => fe(P) = 0 => fe(P) = +1 => fe(P) = +2 // Rééquilibrer P ``` :::: ::: # Rééquilibrage ## Lien avec les cas vus plus tôt ``` fe(P) = -2 && fe(gauche(P)) = -1 => cas 1a fe(P) = -2 && fe(gauche(P)) = +1 => cas 2a fe(P) = +2 && fe(droite(P)) = -1 => cas 2b fe(P) = +2 && fe(droite(P)) = +1 => cas 1b ``` ## Dessiner les différents cas, sur le dessin ci-dessous  # La rotation ## La rotation gauche (5min, matrix)  . . . \footnotesize ``` arbre rotation_gauche(arbre P) si est_non_vide(P) Q = droite(P) droite(P) = gauche(Q) gauche(Q) = P retourne Q retourne P ``` # La rotation en C (1/2) ## La rotation gauche ``` arbre rotation_gauche(arbre P) si est_non_vide(P) Q = droite(P) droite(P) = gauche(Q) gauche(Q) = P retourne Q retourne P ``` ## Écrire le code C correspondant (5min, matrix) 1. Structure de données 2. Fonction `tree_t rotation_left(tree_t tree)` . . . \footnotesize ```C typedef struct _node { int key; struct _node *left, *right; int bf; // balance factor } node; typedef node *tree_t; ``` # La rotation en C (2/2) \footnotesize ```C tree_t rotation_left(tree_t tree) { tree_t subtree = NULL; if (NULL != tree) { subtree = tree->right; tree->right = subtree->left; subtree->left = tree; } return subtree; } ``` . . . * Et la rotation à droite (5min)? . . . ```C tree_t rotation_right(tree_t tree) { tree_t subtree = NULL; if (NULL != tree) { subtree = tree->left; tree->left = subtree->right; subtree->right = tree; } return subtree; } ``` # Exemple de rotation (1/2) ## Insertion de 9? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((5))-->id1((1)); id0-->id2((6)); id2-->id3(( )); id2-->id4((8)); style id3 fill:#fff,stroke:#fff ``` # Exemple de rotation (2/2) ::: columns :::: column ## Quelle rotation et sur quel noeud (5 ou 6)? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((5))-->id1((1)); id0-->id2((6)); id2-->id3(( )); id2-->id4((8)); id4-->id5(( )); id4-->id6((9)); style id3 fill:#fff,stroke:#fff style id5 fill:#fff,stroke:#fff ``` :::: :::: column . . . ## Sur le plus jeune évidemment! ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((5))-->id1((1)); id0-->id2((8)); id2-->id3((6)); id2-->id4((9)); ``` :::: ::: * Cas `1a/b` *check*! # La rotation gauche-droite ## Là c'est plus difficile (cas 2a/b)  # Exercices ## Faire l'implémentation de la double rotation (pas corrigé, 5min) # Exercices ::: columns :::: column ## Insérer 50, ex 10min (matrix) ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((89))-->id1((71)); id0-->id2((90)); id1-->id3((44)); id3-->id4((37)); id3-->id5((61)); id1-->id6((81)) id2-->id7(( )) id2-->id8((100)) style id7 fill:#fff,stroke:#fff ``` :::: :::: column . . . ## Où se fait la rotation? ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((89))-->id1((71)); id0-->id2((90)); id1-->id3((44)); id3-->id4((37)); id3-->id5((61)); id1-->id6((81)) id2-->id7(( )) id2-->id8((100)) id5-->id9((50)) id5-->id10(( )) style id7 fill:#fff,stroke:#fff style id10 fill:#fff,stroke:#fff ``` :::: ::: # Exercices ::: columns :::: column ## Rotation gauche en 44 ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((89))-->id1((71)); id0-->id2((90)); id1-->id3((61)); id1-->id10((81)); id3-->id4((44)); id3-->id5(( )); id4-->id6((37)) id4-->id7((50)) id2-->id8(( )) id2-->id9((100)) style id5 fill:#fff,stroke:#fff style id8 fill:#fff,stroke:#fff ``` :::: :::: column . . . ## Rotation à droite en 71 ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((89))-->id1((61)); id0-->id2((90)); id1-->id3((44)); id1-->id10((71)); id3-->id4((37)); id3-->id5((50)); id2-->id8(( )); id2-->id9((100)); id10-->id11(( )) id10-->id12((81)) style id8 fill:#fff,stroke:#fff style id11 fill:#fff,stroke:#fff ``` :::: ::: # Exercice de la mort Soit l’arbre AVL suivant: ::: columns :::: column ```{.mermaid format=pdf width=400 loc=figs/} graph TD; id0((60))-->id1((40)); id0-->id2((120)); id1-->id3((20)); id1-->id4((50)); id3-->id5((10)); id3-->id6((30)); id2-->id7((100)); id2-->id8((140)); id7-->id9((80)) id7-->id10((110)) id9-->id11((70)) id9-->id12((90)) id8-->id13((130)) id8-->id14((160)) id14-->id15((150)) id14-->id16((170)) ``` :::: :::: column 1. Montrer les positions des insertions de feuille qui conduiront à un arbre désequilibré. 2. Donner les facteurs d’equilibre. 3. Dessiner et expliquer les modifications de l’arbre lors de l’insertion de la valeur `65`. On mentionnera les modifications des facteurs d’équilibre. :::: :::