diff --git a/slides/cours_17.md b/slides/cours_17.md new file mode 100644 index 0000000000000000000000000000000000000000..64487e218ccb4c31dd221803f6dc510518c62884 --- /dev/null +++ b/slides/cours_17.md @@ -0,0 +1,693 @@ +--- +title: "Tri par tas et arbres AVL" +date: "2024-03-24" +--- + +# Questions sur les notions du dernier cours (1/2) + +* Comment représenter un tableau sous forme d'arbre binaire? + +. . . + +* Qu'est-ce qu'un tas? + +. . . + +``` + | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 | +``` + +* Quel est l'arbre que cela représente? + + +# Questions sur les notions du dernier cours (2/2) + + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((5)); + id1-->id3((12)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6((8)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((7)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +# Exercice + +* Trier par tas le tableau + +``` + | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16 +``` + +* Mettez autant de détails que possible. +* Que constatez-vous? +* Postez le résultat sur matrix. + +# L'algorithme du tri par tas (1/2) + +\footnotesize + +## Deux étapes + +1. Entassement (tamisage): transformer l'arbre en tas. +2. Échanger la racine avec le dernier élément et entasser la racine. + +## Pseudo-code d'entassement de l'arbre (15 min, matrix) + +. . . + +```python +rien tri_par_tas(tab) + entassement(tab) + échanger(tab[0], tab[size(tab)-1]) + pour i de size(tab)-1 à 2 + promotion(tab, 0) + échanger(tab[0], tab[i-1]) + +rien entassement(tab) + pour i de size(tab)/2-1 à 0 + promotion(tab, i) + +rien promotion(tab, i) + ind_max = ind_max(tab, i, gauche(i), droite(i)) + si i != ind_max + échanger(tab[i], tab[ind_max]) + promotion(tab, ind_max) +``` + +# L'algorithme du tri par tas (2/2) + +* Fonctions utilitaires + + ```python + entier ind_max(tab, i, g, d) + ind_max = i + si tab[ind_max] < tab[l] + ind_max = l + si tab[ind_mx] < tab[r] + ind_max = r + retourne ind_max + + entier gauche(i) + retourne 2 * i + 1 + + entier droite(i) + retourne 2 * i + 2 + ``` + + +<!-- # L'algorithme du tri par tas (3/4) + +\footnotesize + +## Implémenter en C l'algorithme du tri par tas (matrix, 20min) + +. . . + +```C +void heapsort(int size, int tab[size]) { + heapify(size, tab); + swap(tab, tab + size - 1); + for (int s = size - 1; s > 1; s--) { + sift_up(s, tab, 0); + swap(tab, tab + s - 1); + } +} +void heapify(int size, int tab[size]) { + for (int i = size / 2 - 1; i >= 0; i--) { + sift_up(size, tab, i); + } +} +void sift_up(int size, int tab[size], int i) { + int ind_max = ind_max3(size, tab, i, left(i), right(i)); + if (i != ind_max) { + swap(tab + i, tab + ind_max); + sift_up(size, tab, ind_max); + } +} +``` + +# L'algorithme du tri par tas (4/4) + +\footnotesize + +## Fonctions utilitaires + +. . . + +```C +int ind_max3(int size, int tab[size], int i, int l, int r) { + int ind_max = i; + if (l < size && tab[ind_max] < tab[l]) { + ind_max = l; + } + if (r < size && tab[ind_max] < tab[r]) { + ind_max = r; + } + return ind_max; +} +void swap(int *a, int *b) { + int tmp = *a; + *a = *b; + *b = tmp; +} +int left(int i) { + return 2 * i + 1; +} +int right(int i) { + return 2 * i + 2; +} +``` --> + + +# Complexités + +::: columns + +:::: column + +## Complexité de la recherche + +1. En moyenne? +2. Dans le pire des cas? + +. . . + +1. $O(\log_2(N))$ +2. $O(N)$ + +:::: + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((10))-->id1((9)); + id0-->id8(( )); + id1-->id2((7)); + id1-->id9(( )); + id2-->id3((6)); + id2-->id10(( )); + id3-->id4((5)); + id3-->id11(( )); + style id8 fill:#fff,stroke:#fff + style id9 fill:#fff,stroke:#fff + style id10 fill:#fff,stroke:#fff + style id11 fill:#fff,stroke:#fff +``` + +:::: + +::: + +# Un meilleur arbre + +* Quelle propriété doit satisfaire un arbre pour être $O(\log_2(N))$? + +. . . + +* Si on a environ le même nombre de nœuds dans les sous-arbres. + +## Définition + +Un arbre binaire est parfaitement équilibré si, pour chaque +nœud, la différence entre les nombres de nœuds des sous- +arbres gauche et droit vaut au plus 1. + +* Si l'arbre est **parfaitement équilibré**, alors tout ira bien. +* Quelle est la hauteur (profondeur) d'un arbre parfaitement équilibré? + +. . . + +* $O(\log_2(N))$. + + +# Équilibre parfait ou pas? + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((W))-->id1((B)); + id0-->id8((Y)); + id1-->id2((A)); + id1-->id9(( )); + id8-->id10((X)); + id8-->id11(( )); + style id9 fill:#fff,stroke:#fff + style id11 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +. . . + +``` +É +Q +U +I +L +I +B +R +É +``` + +:::: + +::: + +# Équilibre parfait ou pas? + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((16))-->id1((10)); + id0-->id2((19)); + id1-->id3((8)); + id1-->id4((12)); + id4-->id5((11)); + id4-->id6(( )); + id2-->id7((17)); + id2-->id8(( )); + id7-->id9(( )); + id7-->id10((18)); + style id6 fill:#fff,stroke:#fff + style id8 fill:#fff,stroke:#fff + style id9 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +. . . + +``` +P +A +S + +É +Q +U +I +L +I +B +R +É +``` + +:::: + +::: + +# Arbres AVL + +* Quand est-ce qu'on équilibre un arbre? + +. . . + +* A l'insertion/suppression. +* Maintenir un arbre en état d'équilibre parfait: cher (insertion, suppression). +* On peut "relaxer" la condition d'équilibre: profondeur (hauteur) au lieu du + nombre de nœuds: + * La hauteur $\sim\log_2(N)$. + +## Définition + +Un arbre AVL (Adelson-Velskii et Landis) est un arbre binaire de recherche dans +lequel, pour chaque nœud, la différence de hauteur entre le sous-arbre gauche et droit vaut au plus 1. + +* Relation entre nœuds et hauteur: +$$ +\log_2(1+N)\leq 1+H\leq 1.44\cdot\log_2(2+N),\quad N=10^5,\ 17\leq H \leq 25. +$$ +* Permet l'équilibrage en temps constant: insertion/suppression $O(\log_2(N))$. + +# Notation + +* `hg`: hauteur du sous-arbre gauche. +* `hd`: hauteur du sous-arbre droit. +* `facteur d'équilibre = fe = hd - hg` +* Que vaut `fe` si l'arbre est AVL? + +. . . + +* `fe = {-1, 0, 1}` + + +# AVL ou pas? + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((12))-->id1((10)); + id0-->id2((19)); + id2-->id3((17)); + id2-->id4((97)); +``` + +:::: + +:::: column + +. . . + +``` +A +V +L +``` + +:::: + +::: + +# AVL ou pas? + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((12))-->id1((1)); + id0-->id2((19)); + id2-->id3((17)); + id2-->id4((97)); + id4-->id5((37)); + id4-->id6(( )); + style id6 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +. . . + +``` +P +A +S + +A +V +L +``` + +:::: + +::: + +# 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) + +\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 + +* `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? + +. . . + + + +:::: + +::: \ No newline at end of file diff --git a/slides/figs/cas1a_droite.png b/slides/figs/cas1a_droite.png new file mode 100644 index 0000000000000000000000000000000000000000..9b7b92157e5fe1fa53b7f0e20ecc87f97571caff Binary files /dev/null and b/slides/figs/cas1a_droite.png differ diff --git a/slides/figs/cas1a_gauche.png b/slides/figs/cas1a_gauche.png new file mode 100644 index 0000000000000000000000000000000000000000..c325d8b25cb13e568f24213131d8d77511a9e1ab Binary files /dev/null and b/slides/figs/cas1a_gauche.png differ diff --git a/slides/figs/cas1b_droite.png b/slides/figs/cas1b_droite.png new file mode 100644 index 0000000000000000000000000000000000000000..34344efd9b740261e00c43b30a4c6f9890b74e7b Binary files /dev/null and b/slides/figs/cas1b_droite.png differ diff --git a/slides/figs/cas1b_gauche.png b/slides/figs/cas1b_gauche.png new file mode 100644 index 0000000000000000000000000000000000000000..050eceea5d8a28b24d7c2684ccb4f0f5a0b10cd8 Binary files /dev/null and b/slides/figs/cas1b_gauche.png differ diff --git a/slides/figs/cas2a_droite.png b/slides/figs/cas2a_droite.png new file mode 100644 index 0000000000000000000000000000000000000000..f04fb57308b3aecca93f553005a0b611a158ebca Binary files /dev/null and b/slides/figs/cas2a_droite.png differ diff --git a/slides/figs/cas2a_gauche.png b/slides/figs/cas2a_gauche.png new file mode 100644 index 0000000000000000000000000000000000000000..3ef07573f717b27cc49e97209bb34811c16a5319 Binary files /dev/null and b/slides/figs/cas2a_gauche.png differ diff --git a/slides/figs/cas2b_droite.png b/slides/figs/cas2b_droite.png new file mode 100644 index 0000000000000000000000000000000000000000..f61d56e332600f56aade1584dc579dd1708e1791 Binary files /dev/null and b/slides/figs/cas2b_droite.png differ diff --git a/slides/figs/cas2b_gauche.png b/slides/figs/cas2b_gauche.png new file mode 100644 index 0000000000000000000000000000000000000000..96474155d1814f0f945f1dfe19cf9bb6508ef148 Binary files /dev/null and b/slides/figs/cas2b_gauche.png differ