From bd48cb08d6688e86ece628e64ee96e57086fae29 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Tue, 28 Mar 2023 18:58:50 +0200 Subject: [PATCH] ajout cours 18 --- slides/cours_18.md | 638 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 638 insertions(+) create mode 100644 slides/cours_18.md diff --git a/slides/cours_18.md b/slides/cours_18.md new file mode 100644 index 0000000..909114b --- /dev/null +++ b/slides/cours_18.md @@ -0,0 +1,638 @@ +--- +title: "Arbres AVL" +date: "2023-03-31" +--- + +# 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 + +\footnotesize + +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 + +* `h(v1)=h(v2), h(u)=h(w)`. +* déséquilibre en `C` après insertion dans `v2` + + + +:::: + +:::: column + +## Cas 2a + +* Comment rééquilibrer? + +. . . + +* ramène `u`, `v2`, `w` à la même hauteur (`v1` pas tout à fait). +* `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. + +:::: + +::: + -- GitLab