Skip to content
Snippets Groups Projects
Verified Commit c7b31970 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

maj cours 17 2023

parent 32adc3a6
Branches
No related tags found
No related merge requests found
---
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`
![Après insertion](figs/cas1a_gauche.png)
::::
:::: column
## Cas 1a
* Comment rééquilibrer?
. . .
* ramène `u`, `v` `w` à la même hauteur.
* `v` à droite de `A` (gauche de `B`)
![Après équilibrage](figs/cas1a_droite.png)
::::
:::
# Les cas de déséquilibre
::: columns
:::: column
## Cas 1b (symétrique 1a)
![Après insertion](figs/cas1b_gauche.png)
::::
:::: column
## Cas 1b (symétrique 1a)
* Comment rééquilibrer?
. . .
![Après équilibrage](figs/cas1b_droite.png)
::::
:::
# 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`
![Après insertion](figs/cas2a_gauche.png)
::::
:::: 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`)
![Après équilibrage](figs/cas2a_droite.png)
::::
:::
# Les cas de déséquilibre
::: columns
:::: column
## Cas 2b (symétrique 2a)
![Après insertion](figs/cas2b_gauche.png)
::::
:::: column
## Cas 2b (symétrique 2a)
* Comment rééquilibrer?
. . .
![Après équilibrage](figs/cas2b_droite.png)
::::
:::
\ No newline at end of file
slides/figs/cas1a_droite.png

70.3 KiB

slides/figs/cas1a_gauche.png

71.7 KiB

slides/figs/cas1b_droite.png

66.6 KiB

slides/figs/cas1b_gauche.png

78.3 KiB

slides/figs/cas2a_droite.png

82.1 KiB

slides/figs/cas2a_gauche.png

99.7 KiB

slides/figs/cas2b_droite.png

93.3 KiB

slides/figs/cas2b_gauche.png

100 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment