diff --git a/slides/.gitignore b/slides/.gitignore
index 2000f8a63a7707b72e472719255b506fcc21b692..311559fd6103ddbf587e46500afc3d3a06bb04d6 100644
--- a/slides/.gitignore
+++ b/slides/.gitignore
@@ -3,3 +3,4 @@
 *.markdown
 *.html
 index.md
+.puppeteer.json
diff --git a/slides/.puppeteer.json b/slides/.puppeteer.json
deleted file mode 100644
index 5de4752f0cc5ab97cd3b7391827c2ebe37a75ee8..0000000000000000000000000000000000000000
--- a/slides/.puppeteer.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "executablePath": "/usr/bin/chromium-browser",
-    "args": ["--no-sandbox"]
-}
diff --git a/slides/cours_16.md b/slides/cours_16.md
index c6bb833b870f694611e9b9c7c8f2248470295dd6..f487d541ff9932de59ffcca25b8ac02e870ee152 100644
--- a/slides/cours_16.md
+++ b/slides/cours_16.md
@@ -278,6 +278,7 @@ arbre suppression(arbre, clé)
 arbre parent(arbre, sous_arbre)
     si est_non_vide(arbre)
         actuel = arbre
+        parent = actuel
         clé = clé(sous_arbre)
         faire
             si (clé != clé(actuel))
@@ -319,15 +320,17 @@ arbre suppression(arbre, clé)
 
 # Le pseudo-code  de la suppression
 
+\footnotesize
+
 ## Pour au moins deux enfants (ensemble)
 
 ```
 arbre suppression(arbre, clé)
     sous_arbre = position(arbre, clé) # on revérifie pas que c'est bien la clé
     si est_non_vide(gauche(sous_arbre)) et est_non_vide(droite(sous_arbre))
-        max_gauche = position(sous_arbre, clé)
+        max_gauche = position(gauche(sous_arbre), clé)
         échange(clé(max_gauche), clé(sous_arbre))
-        suppression(sous_arbre, clé) # 
+        suppression(gauche(sous_arbre), clé)
 ```
 
 # Exercices (poster sur matrix)
@@ -1196,112 +1199,3 @@ graph TD;
 * Postez le résultat sur matrix.
 
 
-# L'algorithme du tri par tas (1/4)
-
-## 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 (5 min, matrix)
-
-. . .
-
-```
-tri_par_tas(tab)
-    entassement(tab)
-    échanger(tab[0], tab[size(tab)-1])
-    pour i = size(tab)-1 à 2 
-        promotion(tab, i)
-        échanger(tab[0], tab[i-1])
-entassement(tab)
-    pour i = size(tab) / 2 - 1 jusqu'à 0
-        promotion(tab, i)
-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/4)
-
-* Fonctions utilitaires
-
-```
-int 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
-int gauche(i)
-    retourne 2 * i + 1
-int droite(i)
-    retourne 2 * i + 2
-```
-
-
-# L'algorithme du tri par tas (3/4)
-
-\footnote size
-
-## 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 (3/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;
-}
-```
diff --git a/slides/cours_17.md b/slides/cours_17.md
new file mode 100644
index 0000000000000000000000000000000000000000..e41523f00020741c847c4c1a4257db2f2fc531c1
--- /dev/null
+++ b/slides/cours_17.md
@@ -0,0 +1,1129 @@
+---
+title: "Tri par tas et arbres AVL"
+date: "2022-03-09"
+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
+
+* Comment représenter un tableau sous forme d'arbre binaire?
+
+. . .
+
+* Qu'est-ce qu'un tas?
+
+# Exemple de tri par tas (1/N)
+
+```
+        | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 |
+```
+
+::: columns
+
+:::: column
+
+* Quel est l'arbre que cela représente?
+
+. . .
+
+```{.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
+```
+
+::::
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* On commence à l'indice $N/2 = 5$: `4`.
+* `7 > 4` (enfant `>` parent).
+* intervertir `4` et `7`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((5));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((8));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+. . .
+
+```
+                            *                    *
+        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
+```
+
+# Exemple de tri par tas (2/N)
+
+```
+        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
+```
+
+::: columns
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* On continue à l'indice $N/2-1 = 4$: `12`.
+* Déjà un tas, rien à faire.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((5));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((8));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* On continue à l'indice $N/2-2 = 3$: `5`.
+* `5 < 8`, échanger `8` et `5` (aka `max(2, 5, 8)`)
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((8));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+. . .
+
+```
+        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
+```
+
+# Exemple de tri par tas (3/N)
+
+```
+        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
+```
+
+::: columns
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Indice $N/2-1 = 4$: `12`.
+* Déjà un tas, rien à faire.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((5));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((8));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Indice $N/2-2 = 3$: `5`.
+* `5 < 8`, `5 <=> max(2, 5, 8)`
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((8));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+                   *                *
+        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
+```
+
+# Exemple de tri par tas (4/N)
+
+```
+        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
+```
+
+::: columns
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Indice $N/2-3 = 1$: `16`.
+* Déjà un tas, rien à faire.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((16));
+    id0-->id2((8));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Indice $N/2-4 = 1$: `1`.
+* `1 < 16 && 1 < 8`, `1 <=> max(1, 16, 8)`
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((16))-->id1((1));
+    id0-->id2((8));
+    id1-->id3((12));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+           *   *
+        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
+```
+
+
+# Exemple de tri par tas (5/N)
+
+```
+        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
+```
+
+::: columns
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Recommencer avec `1`.
+* `1 <=> max(1, 12, 7)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((16))-->id1((12));
+    id0-->id2((8));
+    id1-->id3((1));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((10));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Transformer l'arbre en tas.
+
+* Recommencer avec `1`.
+* `1 <=> max(1, 10, 6)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((16))-->id1((12));
+    id0-->id2((8));
+    id1-->id3((10));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((1));
+    id3-->id8((6));
+    id4-->id9((4));
+    id4-->id10(( ));    
+    style id10 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+                *        *               *
+        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
+```
+
+* L'arbre est un tas.
+
+# Exemple de tri par tas (6/N)
+
+```
+        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `16` (`max` de l'arbre) avec `4`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((4))-->id1((12));
+    id0-->id2((8));
+    id1-->id3((10));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((1));
+    id3-->id8((6));
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `4 <=> max(4, 12, 8)`.
+* `4 <=> max(4, 10, 7)`.
+* `4 <=> max(4, 1, 6)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((12))-->id1((10));
+    id0-->id2((8));
+    id1-->id3((6));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((1));
+    id3-->id8((4));
+```
+
+::::
+
+:::
+
+```
+        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
+```
+
+
+# Exemple de tri par tas (7/N)
+
+```
+        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `12` (`max` de l'arbre) avec `4`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((4))-->id1((10));
+    id0-->id2((8));
+    id1-->id3((6));
+    id1-->id4((7));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((1));
+    id3-->id8((  ));
+    style id8 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `4 <=> max(4, 10, 8)`.
+* `4 <=> max(4, 6, 7)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((10))-->id1((7));
+    id0-->id2((8));
+    id1-->id3((6));
+    id1-->id4((4));
+    id2-->id5((2));
+    id2-->id6((5));
+    id3-->id7((1));
+    id3-->id8((  ));
+    style id8 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
+```
+
+# Exemple de tri par tas (8/N)
+
+```
+        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `10` (`max` de l'arbre) avec `1`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((7));
+    id0-->id2((8));
+    id1-->id3((6));
+    id1-->id4((4));
+    id2-->id5((2));
+    id2-->id6((5));
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `1 <=> max(1, 7, 8)`.
+* `5 <=> max(1, 2, 5)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((8))-->id1((7));
+    id0-->id2((5));
+    id1-->id3((6));
+    id1-->id4((4));
+    id2-->id5((2));
+    id2-->id6((1));
+```
+
+::::
+
+:::
+
+```
+        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
+```
+
+# Exemple de tri par tas (9/N)
+
+```
+        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `8` (`max` de l'arbre) avec `1`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((7));
+    id0-->id2((5));
+    id1-->id3((6));
+    id1-->id4((4));
+    id2-->id5((2));
+    id2-->id6((  ));
+    style id6 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `1 <=> max(1, 7, 5)`.
+* `1 <=> max(1, 6, 4)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((7))-->id1((6));
+    id0-->id2((5));
+    id1-->id3((1));
+    id1-->id4((4));
+    id2-->id5((2));
+    id2-->id6((  ));
+    style id6 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
+```
+
+# Exemple de tri par tas (10/N)
+
+```
+        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `7` (`max` de l'arbre) avec `2`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((2))-->id1((6));
+    id0-->id2((5));
+    id1-->id3((1));
+    id1-->id4((4));
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `2 <=> max(2, 6, 5)`.
+* `2 <=> max(2, 1, 4)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((6))-->id1((4));
+    id0-->id2((5));
+    id1-->id3((1));
+    id1-->id4((2));
+```
+
+::::
+
+:::
+
+```
+        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
+```
+
+# Exemple de tri par tas (11/N)
+
+```
+        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `6` (`max` de l'arbre) avec `2`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((2))-->id1((4));
+    id0-->id2((5));
+    id1-->id3((1));
+    id1-->id4((  ));
+    style id4 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `2 <=> max(2, 4, 5)`.
+* `2 <=> max(2, 1, 4)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((5))-->id1((4));
+    id0-->id2((2));
+    id1-->id3((1));
+    id1-->id4((  ));
+    style id4 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+```
+        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
+```
+
+# Exemple de tri par tas (12/N)
+
+```
+        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `5` (`max` de l'arbre) avec `1`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((1))-->id1((4));
+    id0-->id2((2));
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas.
+
+* `1 <=> max(1, 4, 2)`.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((4))-->id1((1));
+    id0-->id2((2));
+```
+
+::::
+
+:::
+
+```
+        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
+```
+
+# Exemple de tri par tas (13/N)
+
+```
+        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
+```
+
+::: columns
+
+:::: column
+
+**But:** Trier les tas.
+
+* Échanger la racine, `4` (`max` de l'arbre) avec `2`.
+* Traiter la racine.
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((2))-->id1((1));
+    id0-->id2(( ));
+    style id2 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+**But:** Trier les tas. Plus rien à trier
+
+* On fait les 2 dernières étapes en vitesse.
+* Échange `2` avec `1`.
+* Il reste que `1`. GGWP!
+
+
+::::
+
+:::
+
+```
+        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
+```
+
+# Exercice (10min)
+
+* 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/4)
+
+\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 (5 min, matrix)
+
+. . .
+
+```
+tri_par_tas(tab)
+    entassement(tab)
+    échanger(tab[0], tab[size(tab)-1])
+    pour i = size(tab)-1 à 2 
+        promotion(tab, 0)
+        échanger(tab[0], tab[i-1])
+entassement(tab)
+    pour i = size(tab) / 2 - 1 jusqu'à 0
+        promotion(tab, i)
+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/4)
+
+* Fonctions utilitaires
+
+```
+int 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
+int gauche(i)
+    retourne 2 * i + 1
+int 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 noeuds 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 neouds:
+    * 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 noeuds 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
+```
+
+::::
+
+:::
+
diff --git a/slides/cours_18.md b/slides/cours_18.md
new file mode 100644
index 0000000000000000000000000000000000000000..a2d1cd07aa272936a5808187eb0f80270bb869a9
--- /dev/null
+++ b/slides/cours_18.md
@@ -0,0 +1,1022 @@
+---
+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}`.
+
+# 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`
+
+![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)
+
+::::
+
+:::
+
+# 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é
+```
+
+![Illustration du `fe`](figs/facteur_equilibre.png){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(gauche(P)) = -1 => cas 1b
+fe(P) = +2 && fe(gauche(P)) = +1 => cas 2b
+```
+
+## Dessiner les différents cas, sur le dessin ci-dessous
+
+![On verra un peu après les rotations.](figs/rotation_gauche_droite.png)
+
+# La rotation
+
+## La rotation gauche (5min, matrix)
+
+![L'arbre de droite devient celui de gauche. Comment?](figs/rotation_gauche_droite.png)
+
+. . .
+
+```
+arbre rotation_gauche(arbre P) 
+    si est_non_vide(P)
+        Q = droite(P)
+        droite(P) = gauche(Q)
+        gauche(Q) = droite(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) = droite(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)`
+
+. . .
+
+```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->lefe;
+    }
+    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)
+
+![La double rotation de l'enfer.](figs/double_rotation_gauche_droite.png)
+
+# Exercices
+
+## Faire l'implémentation de la double rotation (pas corrigé 15min)
+
+. . .
+
+::: 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.
+
+::::
+
+:::
+
+# Encore un petit exercice
+
+* Insérer les noeuds suivants dans un arbre AVL
+
+```
+25 | 60 | 35 | 10 | 5 | 20 | 65 | 45 | 70 | 40 | 50 | 55 | 30 | 15
+```
+
+## Un à un et le/la premier/ère qui poste la bonne réponse sur matrix à un point
+
+# Suppression dans un arbre AVL
+
+
+::: columns
+
+:::: column
+
+## Algorithme par problème: supprimer 10
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((8))-->id1((4));
+    id0-->id2((10));
+    id1-->id3((2));
+    id1-->id4((6));
+    id3-->id5((1));
+    id3-->id6((  ))
+    id4-->id7((  ))
+    id4-->id8((7))
+    id2-->id9((9))
+    id2-->id10((14))
+    id10-->id11((12))
+    id10-->id12((16))
+    style id6 fill:#fff,stroke:#fff
+    style id7 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+. . .
+
+## Algorithme par problème: supprimer 10
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((8))-->id1((4));
+    id0-->id2((12));
+    id1-->id3((2));
+    id1-->id4((6));
+    id3-->id5((1));
+    id3-->id6((  ))
+    id4-->id7((  ))
+    id4-->id8((7))
+    id2-->id9((9))
+    id2-->id10((14))
+    id10-->id11((  ))
+    id10-->id12((16))
+    style id6 fill:#fff,stroke:#fff
+    style id7 fill:#fff,stroke:#fff
+    style id11 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+# Suppression dans un arbre AVL
+
+
+::: columns
+
+:::: column
+
+## Algorithme par problème: supprimer 8
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((8))-->id1((4));
+    id0-->id2((12));
+    id1-->id3((2));
+    id1-->id4((6));
+    id3-->id5((1));
+    id3-->id6((  ))
+    id4-->id7((  ))
+    id4-->id8((7))
+    id2-->id9((9))
+    id2-->id10((14))
+    id10-->id11((  ))
+    id10-->id12((16))
+    style id6 fill:#fff,stroke:#fff
+    style id7 fill:#fff,stroke:#fff
+    style id11 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+. . .
+
+## Algorithme par problème: rotation de 12
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((9))-->id1((4));
+    id0-->id2((12));
+    id1-->id3((2));
+    id1-->id4((6));
+    id3-->id5((1));
+    id3-->id6((  ))
+    id4-->id7((  ))
+    id4-->id8((7))
+    id2-->id9((  ))
+    id2-->id10((14))
+    id10-->id11((  ))
+    id10-->id12((16))
+    style id6 fill:#fff,stroke:#fff
+    style id7 fill:#fff,stroke:#fff
+    style id9 fill:#fff,stroke:#fff
+    style id11 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+# Suppression dans un arbre AVL
+
+::: columns
+
+:::: column
+
+## Algorithme par problème: rotation de 12
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((9))-->id1((4));
+    id0-->id2((14));
+    id1-->id3((2));
+    id1-->id4((6));
+    id3-->id5((1));
+    id3-->id6((  ))
+    id4-->id7((  ))
+    id4-->id8((7))
+    id2-->id9((12))
+    id2-->id10((16))
+    style id6 fill:#fff,stroke:#fff
+    style id7 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+. . .
+
+1. On supprime comme d'habitude.
+2. On rééquilibre si besoin à l'endroit de la suppression.
+
+* Facile non?
+
+. . .
+
+* Plus dur....
+
+::::
+
+:::
+
+# Suppression dans un arbre AVL 2.0
+
+::: columns
+
+:::: column
+
+## Algorithme par problème: suppression de 30
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((50))-->id1((30));
+    id0-->id2((100));
+    id1-->id3((10));
+    id1-->id4((40));
+    id3-->id5((  ));
+    id3-->id6((20))
+    id2-->id7((80))
+    id2-->id8((200))
+    id7-->id9((70))
+    id7-->id10((90))
+    id9-->id11((60))
+    id9-->id12((  ))
+    id8-->id13((  ))
+    id8-->id14((300))
+    style id5 fill:#fff,stroke:#fff
+    style id12 fill:#fff,stroke:#fff
+    style id13 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+. . .
+
+## Algorithme par problème: rotation GD autour de 40
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((50))-->id1((40));
+    id0-->id2((100));
+    id1-->id3((10));
+    id1-->id4((  ));
+    id3-->id5((  ));
+    id3-->id6((20))
+    id2-->id7((80))
+    id2-->id8((200))
+    id7-->id9((70))
+    id7-->id10((90))
+    id9-->id11((60))
+    id9-->id12((  ))
+    id8-->id13((  ))
+    id8-->id14((300))
+    style id4 fill:#fff,stroke:#fff
+    style id5 fill:#fff,stroke:#fff
+    style id12 fill:#fff,stroke:#fff
+    style id13 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+# Suppression dans un arbre AVL 2.0
+
+::: columns
+
+:::: column
+
+## Argl! 50 est déséquilibré!
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((50))-->id1((20));
+    id0-->id2((100));
+    id1-->id3((10));
+    id1-->id4((40));
+    id2-->id7((80))
+    id2-->id8((200))
+    id7-->id9((70))
+    id7-->id10((90))
+    id9-->id11((60))
+    id9-->id12((  ))
+    id8-->id13((  ))
+    id8-->id14((300))
+    style id12 fill:#fff,stroke:#fff
+    style id13 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::: column
+
+. . .
+
+## Algorithme par problème: rotation DG autour de 50
+
+```{.mermaid format=pdf width=400 loc=figs/}
+graph TD;
+    id0((80))-->id1((50));
+    id0-->id2((100));
+    id1-->id3((20));
+    id1-->id4((70));
+    id3-->id5((10));
+    id3-->id6((40));
+    id4-->id9((60))
+    id4-->id10((  ))
+    id2-->id7((90))
+    id2-->id8((200))
+    id8-->id13((  ))
+    id8-->id14((300))
+    style id10 fill:#fff,stroke:#fff
+    style id13 fill:#fff,stroke:#fff
+```
+
+::::
+
+:::
+
+# Résumé de la suppression
+
+1. On supprime comme pour un arbre binaire de recherche.
+2. Si un noeud est déséquilibré, on le rééquilibre.
+    * Cette opération pour déséquilibrer un autre noeud.
+3. On continue à rééquilibrer tant qu'il y a des noeuds à équilibrer.
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
diff --git a/slides/figs/double_rotation_gauche_droite.png b/slides/figs/double_rotation_gauche_droite.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0e8cc8a1321c354d2adecb57a4e34bc5b98e5d2
Binary files /dev/null and b/slides/figs/double_rotation_gauche_droite.png differ
diff --git a/slides/figs/facteur_equilibre.png b/slides/figs/facteur_equilibre.png
new file mode 100644
index 0000000000000000000000000000000000000000..df60e129ff990ed2ae13647d5e1ca56ae739a9ef
Binary files /dev/null and b/slides/figs/facteur_equilibre.png differ
diff --git a/slides/figs/rotation_gauche_droite.png b/slides/figs/rotation_gauche_droite.png
new file mode 100644
index 0000000000000000000000000000000000000000..28f7476188fc858ecd5fc37b32b933b2956f9d27
Binary files /dev/null and b/slides/figs/rotation_gauche_droite.png differ
diff --git a/slides/gen_index.sh b/slides/gen_index.sh
index 507d3f8f21405d2b295cacd80bd1170aeda8a0b9..5c72edf6c43ccbb286b6af2401b7c0e789f0a267 100755
--- a/slides/gen_index.sh
+++ b/slides/gen_index.sh
@@ -1,5 +1,26 @@
 #!/bin/bash
 
+set -e
+
+function get_info() {
+    local field=$(echo "$fullName" | sed "$2q;d" $1);
+    IFS=$3;
+    local field=($field); 
+    if [ "${field}" != $5 ]; then
+        return 1
+    fi
+    local field=${field[1]};
+    IFS=$4;
+    local field=($field);
+    local field=${field[1]};
+    echo "$field"
+}
+
+function fail() {
+    printf '%s\n' "$1" >&2 ## Send message to stderr.
+    exit "${2-1}" ## Return a code specified by $2, or 1 by default.
+}
+
 OIFS=$IFS
 NUM_LINE=2
 PREFIX=""
@@ -8,36 +29,27 @@ PREFIX=""
 classes=()
 for i in *.md; do
     [ -f "$i" ] || break
-    comp=$(echo "$fullName" | sed "${NUM_LINE}q;d" $i)
-    date=$(echo "$fullName" | sed "3q;d" $i)
-    IFS=':' 
-    comp=($comp); 
-    comp=${comp[1]}
-    date=($date); 
-    date=${date[1]}
-    # echo $comp
-    IFS='"'
-    comp=($comp)
-    comp=${comp[1]}
-    date=($date); 
-    date=${date[1]}
-    # echo $comp | awk '{ print substr( $0, 1, length($0)-1 ) }'
-    # echo $comp
-    # date=sed "${NUM_LINE}q;d" $i
+    date="$(get_info $i 3 ":" '"' "date")"
+    if [ "$date" == 1 ]; then
+        fail "Error date field not found"
+    fi
+    comp="$(get_info $i 2 ":" '"' "title")"
+    if [ "$comp" == 1 ]; then
+        fail "Error title field not found"
+    fi
     i="${i%.*}"
     class="[${date} ${comp}](${PREFIX}${i}.pdf)"
-    classes+=($class)
-    # echo "[${date} ${comp}](${PREFIX}${i}.pdf)" >> index.md
+    classes+=("$class")
 done
 IFS=$'\n'
 classes=($(sort <<<"${classes[*]}"))
 date=$(date '+%Y-%m-%d')
 echo "---" >> index.md
-echo "title: Slides du cours d'Algorithmique" >> index.md
-echo "date: ${date}" >> index.md
+echo "title: \"Slides du cours d'algorithmique\"" >> index.md
+echo "date: \"${date}\"" >> index.md
 echo "---" >> index.md
 echo "" >> index.md
-echo "# Tous les slides du cours d'Algorithmique" >> index.md
+echo "# Tous les slides du cours d'algorithmique" >> index.md
 echo "" >> index.md
 for i in ${classes[*]}; do
     echo "* $i" >> index.md
diff --git a/source_codes/arbres_AVL/.gitignore b/source_codes/arbres_AVL/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f8a1ca8adedba78aa24db2659b28c80e68e737f0
--- /dev/null
+++ b/source_codes/arbres_AVL/.gitignore
@@ -0,0 +1,4 @@
+bin_tree.o
+avl.o
+main
+main.o
diff --git a/source_codes/arbres_AVL/Makefile b/source_codes/arbres_AVL/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..88318d040b26be3d320f34562fdb9066f4b418ea
--- /dev/null
+++ b/source_codes/arbres_AVL/Makefile
@@ -0,0 +1,25 @@
+CC:=gcc
+# SAN:=-fsanitize=address
+CFLAGS:=-Wall -Wextra -pedantic -g $(SAN)
+LDFLAGS:=-lm $(SAN)
+SOURCES := $(wildcard *.c)
+OBJECTS := $(patsubst %.c, %.o, $(SOURCES))
+
+all: main $(OBJECTS)
+
+main: main.c bin_tree.o avl.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	@echo $@ >> .gitignore
+
+bin_tree.o: bin_tree.h
+avl.o: avl.h
+
+.PHONY: clean all
+
+clean:
+	rm -f *.o main .gitignore
+
diff --git a/source_codes/arbres_AVL/avl.c b/source_codes/arbres_AVL/avl.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c5cbce1aa7d1ffab08e85141f009e98f29a72bd
--- /dev/null
+++ b/source_codes/arbres_AVL/avl.c
@@ -0,0 +1,174 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "avl.h"
+
+void avl_print(arbre tree,int N) {
+   if (N <= 0) {
+      N = 1;
+   }
+   if (NULL != tree) {
+      avl_print(tree->child[1],N+2);
+      for (int i=0;i<N;i++) {
+         printf("    ");
+      }
+      printf("%d\n",tree->key);            
+      avl_print(tree->child[0],N+2);
+   } 
+}
+
+node* avl_desequilibre(arbre tree,clef key) {
+   node* crt = tree;
+   node* parent = NULL;
+   int h_prec[2] = {0,0};
+
+   while (NULL != crt && crt->key != key) {
+      if (abs(crt->h[1]-crt->h[0]) == 2) {
+         parent = crt;
+         h_prec[0] = parent->h[0];
+         h_prec[1] = parent->h[1];
+         parent->h[key > parent->key] -= 1;
+      }
+      crt = crt->child[key > crt->key];
+   }
+   if (NULL != parent) {
+      parent->h[0] = h_prec[0];
+      parent->h[1] = h_prec[1];
+   }
+   return parent;
+}
+
+int avl_height(arbre tree) {
+   if (NULL == tree) {
+      return 0;
+   } else {   
+      return 1+fmax(avl_height(tree->child[0]),avl_height(tree->child[1]))+0.01;
+   }
+}
+
+void avl_heights(arbre tree) {
+   for (int i=0;i<2;i++) {
+      if (NULL != tree->child[i]) {
+         avl_heights(tree->child[i]);
+         tree->h[i] = 1+fmax(tree->child[i]->h[0],tree->child[i]->h[1])+0.01;
+      } else {
+         tree->h[i] = 0;
+      }
+   }
+}
+
+void avl_height_node(node* nd) {
+   for (int i=0;i<2;i++) {
+      if (NULL != nd->child[i]) {
+         nd->h[i] = 1+fmax(nd->child[i]->h[0],nd->child[i]->h[1])+0.01;
+      } else {
+         nd->h[i] = 0;
+      }
+   }
+}
+
+static node* avl_rot(node* P,bool right) {
+   node* Q = NULL;
+   if (NULL != P) {
+      Q                = P->child[right];
+      P->child[right]  = Q->child[!right];
+      Q->child[!right] = P;
+      avl_height_node(P);
+      avl_height_node(Q);
+   }
+   return Q;
+}
+
+node* avl_rot_g(node* nd) {
+   return avl_rot(nd,false);
+}
+
+node* avl_rot_d(node* nd) {
+   return avl_rot(nd,true);
+}
+
+static node* avl_rot2(node* nd,bool dg) {
+   nd->child[dg] = avl_rot(nd->child[dg],dg);
+   return avl_rot(nd,!dg);
+}
+
+node* avl_rot_gd(node* nd) {
+   return avl_rot2(nd,false);
+}
+
+node* avl_rot_dg(node* nd) {
+   return avl_rot2(nd,true);
+}
+
+static void avl_rotation(node* nd,bool right) {
+   node* new_nd = calloc(1,sizeof(node));
+   new_nd->key = nd->key;
+   new_nd->child[right] = nd->child[right];
+   new_nd->child[!right] = nd->child[!right]->child[right];
+   node* tmp = nd->child[!right]; 
+
+   nd->key = nd->child[!right]->key;
+   nd->child[right] = new_nd;
+   nd->child[!right] = nd->child[!right]->child[!right];
+   avl_height_node(new_nd);
+   avl_height_node(nd);
+   free(tmp);
+}
+
+void avl_rotation_g(node* nd) {
+   avl_rotation(nd,false);
+}
+
+void avl_rotation_d(node* nd) {
+   avl_rotation(nd,true);
+}
+
+static void avl_rotation2(node* nd,bool dg) {
+   avl_rotation(nd->child[dg],dg);
+   avl_rotation(nd,!dg);
+}
+
+void avl_rotation_gd(node* nd) {
+   avl_rotation2(nd,false);
+}
+
+void avl_rotation_dg(node* nd) {
+   avl_rotation2(nd,true);
+}
+
+void avl_reequilibre(node* nd) {
+   switch(nd->h[1]-nd->h[0]) {
+      case +2:
+         switch(nd->child[1]->h[1] - nd->child[1]->h[0]) {
+            case +1: avl_rotation_g(nd); break;
+            case -1: avl_rotation_dg(nd);
+         }
+         break;
+      case -2:
+         switch(nd->child[0]->h[1] - nd->child[0]->h[0]) {
+            case -1: avl_rotation_d(nd); break;
+            case +1: avl_rotation_gd(nd);
+         }
+   }
+}
+
+void avl_insert(clef key,arbre* tree,arbre* deseq) {
+   if (NULL == *tree) {
+      *tree = calloc(1,sizeof(node));
+      (*tree)->key = key;
+      *deseq = NULL;
+   } else {
+      avl_insert(key,&((*tree)->child[key > (*tree)->key]),deseq);
+      if (NULL == *deseq) {
+         (*tree)->h[key > (*tree)->key] 
+             = 1+fmax((*tree)->child[key > (*tree)->key]->h[0],
+                      (*tree)->child[key > (*tree)->key]->h[1]);
+      } 
+      if (abs((*tree)->h[1]-(*tree)->h[0]) == 2 && NULL == *deseq) {
+         *deseq = *tree;
+      }
+   }
+}
+
diff --git a/source_codes/arbres_AVL/avl.h b/source_codes/arbres_AVL/avl.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f31a45de877550098b9ace6e2447bcb0e08a21b
--- /dev/null
+++ b/source_codes/arbres_AVL/avl.h
@@ -0,0 +1,87 @@
+#ifndef AVL_H
+#define AVL_H
+
+typedef int clef;
+
+typedef struct _node {
+   clef key;
+   struct _node* child[2];
+   int h[2];
+} node;
+
+typedef node* arbre;
+
+//----------------------------------------------------------
+// fonction qui imprime un arbre                          --
+//----------------------------------------------------------
+void avl_print(arbre tree,int N);
+//----------------------------------------------------------
+// fonction qui retourne le premier noeud d�s�quilibr� et --
+// met � jour les hauteurs sur le chemin d'insertion      --
+//----------------------------------------------------------
+node* avl_desequilibre(arbre tree,clef key);
+//----------------------------------------------------------
+// fonction qui calcule la hauteur d'un arbre             --
+//----------------------------------------------------------
+int avl_height(arbre tree);
+//----------------------------------------------------------
+// fonction qui remet � jour les hauteurs des noeuds      --
+// apr�s le r��quilibrage                                 --
+//----------------------------------------------------------
+void avl_heights(arbre tree);
+//----------------------------------------------------------
+// fonction qui remet � jour les hauteurs des noeuds      --
+// apr�s le r��quilibrage                                 --
+//----------------------------------------------------------
+void avl_height_node(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une rotation gauche sur le       --
+// noeud d�s�quilibr�                                     --
+//----------------------------------------------------------
+node* avl_rot_g(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une rotation droite sur le       --
+// noeud d�s�quilibr�                                     --
+//----------------------------------------------------------
+node* avl_rot_d(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une double rotation gauche       --
+// droite sur le noeud d�s�quilibr�                       --
+//----------------------------------------------------------
+node* avl_rot_gd(node* nd); 
+//----------------------------------------------------------
+// fonction qui effectue une double rotation droite       --
+// gauche sur le noeud d�s�quilibr�                       --
+//----------------------------------------------------------
+node* avl_rot_dg(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une rotation gauche sur le       --
+// noeud d�s�quilibr�                                     --
+//----------------------------------------------------------
+void avl_rotation_g(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une rotation droite sur le       --
+// noeud d�s�quilibr�                                     --
+//----------------------------------------------------------
+void avl_rotation_d(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une double rotation gauche       --
+// droite sur le noeud d�s�quilibr�                       --
+//----------------------------------------------------------
+void avl_rotation_gd(node* nd);
+//----------------------------------------------------------
+// fonction qui effectue une double rotation droite       --
+// gauche sur le noeud d�s�quilibr�                       --
+//----------------------------------------------------------
+ void avl_rotation_dg(node* nd);  
+//----------------------------------------------------------
+// fonction qui r��quilibre l'arbre                       --
+//----------------------------------------------------------
+void avl_reequilibre(node* nd);
+//----------------------------------------------------------
+// fonction qui ins�re une valeur dans l'arbre            --
+//----------------------------------------------------------
+void avl_insert(clef key,arbre*  tree, arbre* deseq);
+
+#endif
+
diff --git a/source_codes/arbres_AVL/bin_tree.c b/source_codes/arbres_AVL/bin_tree.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a38e140a09d76ed2fb3c03acdd4419cde92b784
--- /dev/null
+++ b/source_codes/arbres_AVL/bin_tree.c
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <math.h>
+#include "bin_tree.h"
+
+static node* position(arbre tree,int cle) {
+   node* crt = tree;
+   if (NULL != crt) {
+      while (cle != crt->key 
+             && NULL != crt->child[(cle > crt->key)]) {
+         crt = crt->child[(cle > crt->key)];
+      }
+   }
+   return crt;
+}
+
+int arbre_depth(arbre tree) {
+   if (NULL == tree) {
+      return 0;
+   } else {   
+      return 1+fmax(arbre_depth(tree->child[0]),arbre_depth(tree->child[1]));
+   }
+}
+
+int arbre_size(arbre tree) {
+   if (NULL == tree) {
+      return 0;
+   } else {   
+      return 1+arbre_size(tree->child[0])+arbre_size(tree->child[1]);
+   }
+}
+
+bool arbre_insert(arbre* tree,int cle) {
+   if (NULL == *tree) {
+      *tree = calloc(1,sizeof(node));
+      (*tree)->key = cle;
+   } else {
+      node* nd = position(*tree,cle);
+      if (cle != nd->key) {
+         nd->child[(cle > nd->key)] = calloc(1,sizeof(node));
+         nd->child[(cle > nd->key)]->key = cle;
+      } else {
+         return false;
+      }
+   }
+   return true;
+}
+
+static node* parent(arbre tree,node* nd) {
+   assert(NULL != tree && NULL != nd);
+   node* parent = NULL;
+   if (nd != tree) {
+      node* crt = tree;
+      int cle = nd->key;
+      do  {
+         parent = crt;
+         if (cle != crt->key) {
+            crt = crt->child[(cle > crt->key)];
+         }
+      } while (crt != nd);
+   }
+   return parent;
+}
+
+
+
+
+
+
+
+bool arbre_delete(arbre* tree,int cle) {
+   node* nd = position(*tree,cle);
+   
+   if (NULL == nd || cle != nd->key) {
+      return false;
+   }
+
+   // terminal node
+   if (NULL == nd->child[0] && NULL == nd->child[1]) {
+      node* nd_parent = parent(*tree,nd);
+      if (NULL == nd_parent) { // single node tree
+         *tree = NULL;
+      } else {
+         nd_parent->child[(nd == nd_parent->child[1])] = NULL;
+      }
+      free(nd);
+      return true;
+   }
+
+   for (int ind=0;ind<2;ind++) {
+      if (NULL != nd->child[ind]) {
+         node* next = position(nd->child[ind],cle);
+         int val = next->key;
+         if (NULL == nd->child[ind]->child[ind^1]) {
+            nd->child[ind] = next->child[ind];
+            free(next);
+         } else {
+            bool res = arbre_delete(tree,next->key);
+         }
+         nd->key = val;
+         return true;
+      }
+   }
+}
+
+void arbre_print(arbre tree,int N) {
+   if (N <= 0) {
+      N = 1;
+   }
+   if (NULL != tree) {
+      arbre_print(tree->child[1],N+1);
+      for (int i=0;i<N;i++) {
+         printf("    ");
+      }
+      printf("%d\n",tree->key);            
+      arbre_print(tree->child[0],N+1);
+   } 
+}
+
+bool arbre_search(arbre tree,int cle) {
+   node* nd = position(tree,cle);
+   return (NULL != nd && cle == nd->key);
+}
+
+
diff --git a/source_codes/arbres_AVL/bin_tree.h b/source_codes/arbres_AVL/bin_tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..25843d5df1a9430ea0d58997f84289b166b5dcc8
--- /dev/null
+++ b/source_codes/arbres_AVL/bin_tree.h
@@ -0,0 +1,39 @@
+#ifndef BIN_TREE_H
+#define BIN_TREE_H
+
+// Structure pour un arbre binaire
+typedef int cle;
+typedef struct _node {
+  cle key;
+  struct _node* child[2];
+} node;
+typedef node* arbre;
+
+// Fonctionnalités pour un arbre binaire ordonné
+bool arbre_search(arbre tree,int cle);
+bool arbre_insert(arbre* tree,int cle);
+bool arbre_delete(arbre* tree,int cle);
+void arbre_print(arbre tree,int N);
+int arbre_depth(arbre tree);
+int arbre_size(arbre tree);
+#endif 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source_codes/arbres_AVL/main.c b/source_codes/arbres_AVL/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..3454c3982330b2606b2b840f92f9b46a7bb396e4
--- /dev/null
+++ b/source_codes/arbres_AVL/main.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "avl.h"
+
+void main() {
+   arbre mon_arbre = NULL, deseq = NULL;
+   char nbr[20];
+   while (true) {
+      printf("Nombre: ");
+      scanf("%s",nbr);
+      if (strcmp(nbr,"quit") == 0) break;
+      avl_insert(atoi(nbr),&mon_arbre,&deseq);
+      if (NULL != deseq) {
+         printf("Desequilibre!");
+         avl_reequilibre(deseq);
+      }
+      printf("\n\n");
+      avl_print(mon_arbre,1);
+      printf("\n\n");
+   }
+}
diff --git a/source_codes/arbres_binaires/.gitignore b/source_codes/arbres_binaires/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..87605a2522b98767e8215384d43a1d4012b565d8
--- /dev/null
+++ b/source_codes/arbres_binaires/.gitignore
@@ -0,0 +1,9 @@
+bin_tree.o
+main
+tree_search
+bin_tree_main
+arbre_binaire.o
+bin_tree_main.o
+bin_tree_part.o
+main.o
+tree_search.o
diff --git a/source_codes/arbres_binaires/Makefile b/source_codes/arbres_binaires/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..28afaca45224d2847e47cd133713903d23187258
--- /dev/null
+++ b/source_codes/arbres_binaires/Makefile
@@ -0,0 +1,33 @@
+CC:=gcc
+# SAN:=-fsanitize=address
+CFLAGS:=-Wall -Wextra -pedantic -g $(SAN)
+LDFLAGS:=-lm $(SAN)
+SOURCES := $(wildcard *.c)
+OBJECTS := $(patsubst %.c, %.o, $(SOURCES))
+
+all: main tree_search bin_tree_main $(OBJECTS)
+
+tree_search: tree_search.c bin_tree.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+bin_tree_main: bin_tree_main.c bin_tree.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+main: main.c bin_tree.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	@echo $@ >> .gitignore
+
+bin_tree.o: bin_tree.h
+bin_tree_rec.o: bin_tree_rec.h
+
+.PHONY: clean all
+
+clean:
+	rm -f *.o main tree_search bin_tree_main .gitignore
+
diff --git a/source_codes/arbres_binaires/arbre_binaire.c b/source_codes/arbres_binaires/arbre_binaire.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a6a655d14b30ff00b0b96b2ba857c4df0086c0e
--- /dev/null
+++ b/source_codes/arbres_binaires/arbre_binaire.c
@@ -0,0 +1,132 @@
+#include "arbre_binaire.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static node *position(arbre tree, int cle) {
+    node *crt = tree;
+    if (NULL != tree) {
+        do {
+            if (cle < crt->key) {
+                if (NULL == crt->gauche) {
+                    break;
+                }
+                crt = crt->gauche;
+            } else if (cle > crt->key) {
+                if (NULL == crt->droite) {
+                    break;
+                }
+                crt = crt->droite;
+            }
+        } while (crt->key != cle);
+    }
+    return crt;
+}
+
+bool arbre_insert(arbre *tree, int cle) {
+    if (NULL == *tree) {
+        *tree        = calloc(1, sizeof(node));
+        (*tree)->key = cle;
+    } else {
+        node *nd = position(*tree, cle);
+        if (cle < nd->key) {
+            nd->gauche      = calloc(1, sizeof(node));
+            nd->gauche->key = cle;
+        } else if (cle > nd->key) {
+            nd->droite      = calloc(1, sizeof(node));
+            nd->droite->key = cle;
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+static node *parent(arbre tree, node *nd) {
+    assert(NULL != tree && NULL != nd);
+    node *parent = NULL;
+    if (nd != tree) {
+        node *crt = tree;
+        int cle   = nd->key;
+        do {
+            parent = crt;
+            if (cle < crt->key) {
+                crt = crt->gauche;
+            } else if (cle > crt->key) {
+                crt = crt->droite;
+            }
+        } while (crt != nd);
+    }
+    return parent;
+}
+
+bool arbre_delete(arbre *tree, int cle) {
+    node *nd = position(*tree, cle);
+
+    if (NULL == nd || cle != nd->key) {
+        return false;
+    }
+
+    // terminal node
+    if (NULL == nd->gauche && NULL == nd->droite) {
+        node *nd_parent = parent(*tree, nd);
+        if (NULL == nd_parent) { // single node tree
+            *tree = NULL;
+        } else if (nd == nd_parent->gauche) {
+            nd_parent->gauche = NULL;
+        } else if (nd == nd_parent->droite) {
+            nd_parent->droite = NULL;
+        }
+        free(nd);
+        return true;
+    }
+
+    if (NULL != nd->gauche) {
+        node *child = position(nd->gauche, cle);
+        int val     = child->key;
+        if (NULL == nd->gauche->droite) {
+            nd->gauche = child->gauche;
+            free(child);
+        } else {
+            bool res = arbre_delete(tree, child->key);
+        }
+        nd->key = val;
+        return true;
+    }
+
+    if (NULL != nd->droite) {
+        node *child = position(nd->droite, cle);
+        int val     = child->key;
+        if (NULL == nd->droite->gauche) {
+            nd->droite = child->droite;
+            free(child);
+        } else {
+            bool res = arbre_delete(tree, child->key);
+        }
+        nd->key = val;
+        return true;
+    }
+
+    return false;
+}
+
+void arbre_print(arbre tree, int N) {
+    if (N <= 0) {
+        N = 1;
+    }
+    if (NULL != tree) {
+        arbre_print(tree->droite, N + 1);
+        for (int i = 0; i < N; i++) {
+            printf("    ");
+        }
+        printf("%d\n", tree->key);
+        arbre_print(tree->gauche, N + 1);
+    }
+}
+
+bool arbre_search(arbre tree, int cle) {
+    node *nd = position(tree, cle);
+    return (NULL != nd && cle == nd->key);
+}
+
diff --git a/source_codes/arbres_binaires/arbre_binaire.h b/source_codes/arbres_binaires/arbre_binaire.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca616c6d0803fb5d3550373cdf9dfb56e98b613f
--- /dev/null
+++ b/source_codes/arbres_binaires/arbre_binaire.h
@@ -0,0 +1,21 @@
+#ifndef ARBRE_BINAIRE_H
+#define ARBRE_BINAIRE_H
+
+#include <stdbool.h>
+
+// Structure pour un arbre binaire
+typedef int cle;
+typedef struct _node {
+    cle key;
+    struct _node *gauche;
+    struct _node *droite;
+} node;
+typedef node *arbre;
+
+// Fonctionnalités pour un arbre binaire ordonné
+bool arbre_search(arbre tree, int cle);
+bool arbre_insert(arbre *tree, int cle);
+bool arbre_delete(arbre *tree, int cle);
+void arbre_print(arbre tree, int N);
+#endif
+
diff --git a/source_codes/arbres_binaires/bin_tree.c b/source_codes/arbres_binaires/bin_tree.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b2aa0f9240468ca4da0e2655f2cfaafd1477ed6
--- /dev/null
+++ b/source_codes/arbres_binaires/bin_tree.c
@@ -0,0 +1,148 @@
+#include "bin_tree.h"
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static node *position(arbre tree, cle c) {
+    node *crt = tree;
+    if (NULL != crt) {
+        while (c != crt->key && NULL != crt->child[(c > crt->key)]) {
+            crt = crt->child[(c > crt->key)];
+        }
+    }
+    return crt;
+}
+
+bool arbre_is_empty(arbre tree) {
+    return NULL == tree;
+}
+
+int arbre_depth(arbre tree) {
+    if (arbre_is_empty(tree)) {
+        return 0;
+    } else {
+        return 1 +
+               fmax(arbre_depth(tree->child[0]), arbre_depth(tree->child[1]));
+    }
+}
+
+int arbre_size(arbre tree) {
+    if (arbre_is_empty(tree)) {
+        return 0;
+    } else {
+        return 1 + arbre_size(tree->child[0]) + arbre_size(tree->child[1]);
+    }
+}
+
+static node *create_node(int val) {
+    node *nd = calloc(1, sizeof(node));
+    nd->key  = val;
+    return nd;
+}
+
+arbre arbre_insert(arbre tree, cle c) {
+    if (arbre_is_empty(tree)) {
+        tree = create_node(c);
+    } else {
+        node *nd                 = position(tree, c);
+        nd->child[(c > nd->key)] = create_node(c);
+    }
+    return tree;
+}
+
+static node *parent(arbre tree, node *nd) {
+    assert(!arbre_is_empty(tree) && NULL != nd);
+    node *parent = NULL;
+    if (nd != tree) {
+        node *crt = tree;
+        cle c     = nd->key;
+        do {
+            parent = crt;
+            if (c != crt->key) {
+                crt = crt->child[(c > crt->key)];
+            }
+        } while (crt != nd);
+    }
+    return parent;
+}
+
+bool arbre_search(arbre tree, cle c) {
+    node *nd = position(tree, c);
+    return (NULL != nd && c == nd->key);
+}
+
+bool arbre_delete(arbre *tree, cle c) {
+    node *nd = position(*tree, c);
+    if (NULL == nd || c != nd->key) {
+        return false;
+    }
+    // noeud terminal ou avec 1 enfant
+    if (arbre_is_empty(nd->child[0]) || arbre_is_empty(nd->child[1])) {
+        node *nd_parent = parent(*tree, nd);
+        if (NULL == nd_parent) { // nd est la racine
+            *tree = nd->child[(NULL != nd->child[1])];
+        } else {
+            nd_parent->child[(nd == nd_parent->child[1])] =
+                nd->child[(NULL != nd->child[1])];
+        }
+        free(nd);
+    } else {                                    // noeud interne (2 enfants)
+        node *next = position(nd->child[1], c); // next a 0 ou 1 enfant
+        cle tmp    = next->key;
+        bool res   = arbre_delete(tree, tmp);
+        nd->key    = tmp;
+    }
+    return true;
+}
+
+bool arbre_delete_bis(arbre *tree, cle c) {
+    node *nd = position(*tree, c);
+
+    if (NULL == nd || c != nd->key) {
+        return false;
+    }
+
+    // terminal node
+    if (arbre_is_empty(nd->child[0]) && arbre_is_empty(nd->child[1])) {
+        node *nd_parent = parent(*tree, nd);
+        if (NULL == nd_parent) { // single node tree
+            *tree = NULL;
+        } else {
+            nd_parent->child[(nd == nd_parent->child[1])] = NULL;
+        }
+        free(nd);
+        return true;
+    }
+
+    for (int ind = 0; ind < 2; ind++) {
+        if (!arbre_is_empty(nd->child[ind])) {
+            node *next = position(nd->child[ind], c);
+            int val    = next->key;
+            if (NULL == nd->child[ind]->child[ind ^ 1]) {
+                nd->child[ind] = next->child[ind];
+                free(next);
+            } else {
+                bool res = arbre_delete(tree, next->key);
+            }
+            nd->key = val;
+            return true;
+        }
+    }
+    return false;
+}
+
+void arbre_print(arbre tree, int N) {
+    if (N <= 0) {
+        N = 1;
+    }
+    if (NULL != tree) {
+        arbre_print(tree->child[1], N + 1);
+        for (int i = 0; i < N; i++) {
+            printf("    ");
+        }
+        printf("%d\n", tree->key);
+        arbre_print(tree->child[0], N + 1);
+    }
+}
diff --git a/source_codes/arbres_binaires/bin_tree.h b/source_codes/arbres_binaires/bin_tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f7fd35fcc237bee5939ccd6016f83ad7f0b6542
--- /dev/null
+++ b/source_codes/arbres_binaires/bin_tree.h
@@ -0,0 +1,23 @@
+#ifndef BIN_TREE_H
+#define BIN_TREE_H
+
+#include <stdbool.h>
+
+// Structure pour un arbre binaire
+typedef int cle;
+typedef struct _node {
+    cle key;
+    struct _node *child[2];
+} node;
+typedef node *arbre;
+
+// Fonctionnalités pour un arbre binaire ordonné
+bool arbre_is_empty(arbre tree);
+bool arbre_search(arbre tree, cle c);
+arbre arbre_insert(arbre tree, cle c);
+bool arbre_delete(arbre *tree, cle c);
+void arbre_print(arbre tree, int N);
+int arbre_depth(arbre tree);
+int arbre_size(arbre tree);
+#endif
+
diff --git a/source_codes/arbres_binaires/bin_tree_main.c b/source_codes/arbres_binaires/bin_tree_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..b5500ddf3bd39e904bacf13501a9a479fb0974e2
--- /dev/null
+++ b/source_codes/arbres_binaires/bin_tree_main.c
@@ -0,0 +1,25 @@
+#include "bin_tree.h"
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void main() {
+    bool b     = false;
+    arbre tree = NULL;
+    arbre_print(tree, 1);
+    do {
+        printf("insert val = ");
+        int val;
+        scanf("%d", &val);
+        b = arbre_insert(tree, val);
+        arbre_print(tree, 1);
+    } while (b);
+    node *nd;
+    do {
+        printf("delete val = ");
+        int val;
+        scanf("%d", &val);
+        b = arbre_delete(&tree, val);
+        arbre_print(tree, 1);
+    } while (NULL != tree);
+}
diff --git a/source_codes/arbres_binaires/bin_tree_part.c b/source_codes/arbres_binaires/bin_tree_part.c
new file mode 100644
index 0000000000000000000000000000000000000000..dbdd5d5d4516cd9f37d7a458edefb1c840873d01
--- /dev/null
+++ b/source_codes/arbres_binaires/bin_tree_part.c
@@ -0,0 +1,110 @@
+#include "bin_tree_part.h"
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static node *position(arbre tree, int cle) {
+    node *crt = tree;
+    if (NULL != crt) {
+        while (cle != crt->key && NULL != crt->child[(cle > crt->key)]) {
+            crt = crt->child[(cle > crt->key)];
+        }
+    }
+    return crt;
+}
+
+static node *parent(arbre tree, node *nd) {
+    assert(NULL != tree && NULL != nd);
+    node *parent = NULL;
+    int cle      = nd->key;
+    if (nd != tree) {
+        node *crt = tree;
+        do {
+            //à compléter
+        } while (crt != nd);
+    }
+    return parent;
+}
+
+int arbre_depth(arbre tree) {
+    if (NULL == tree) {
+        return 0;
+    } else {
+        return 1 +
+               fmax(arbre_depth(tree->child[0]), arbre_depth(tree->child[1]));
+    }
+}
+
+int arbre_size(arbre tree) {
+    //à compléter
+    return 0;
+}
+
+bool arbre_insert(arbre *tree, int cle) {
+    if (NULL == *tree) {
+        *tree        = calloc(1, sizeof(node));
+        (*tree)->key = cle;
+    } else {
+        node *nd = position(*tree, cle);
+        if (cle != nd->key) {
+            //à compléter
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool arbre_delete(arbre *tree, int cle) {
+    node *nd = position(*tree, cle);
+    if (NULL == nd || cle != nd->key) {
+        return false;
+    }
+    // noeud terminal
+    if (NULL == nd->child[0] && NULL == nd->child[1]) {
+        node *nd_parent = parent(*tree, nd);
+        // à compléter:
+        //    considérer les cas de l'arbre à un seul/plusieurs noeuds
+        free(nd);
+        return true;
+    }
+
+    // noeud interne et récursion
+    for (int ind = 0; ind < 2; ind++) {
+        if (NULL != nd->child[ind]) {
+            node *next = position(nd->child[ind], cle);
+            int val    = next->key;
+            if (NULL == nd->child[ind]->child[ind ^ 1]) {
+                nd->child[ind] = next->child[ind];
+                free(next);
+            } else {
+                bool res = arbre_delete(tree, next->key);
+            }
+            nd->key = val;
+            return true;
+        }
+    }
+    return false;
+}
+
+void arbre_print(arbre tree, int N) {
+    if (N <= 0) {
+        N = 1;
+    }
+    if (NULL != tree) {
+        arbre_print(tree->child[1], N + 1);
+        for (int i = 0; i < N; i++) {
+            printf("    ");
+        }
+        printf("%d\n", tree->key);
+        arbre_print(tree->child[0], N + 1);
+    }
+}
+
+bool arbre_search(arbre tree, int cle) {
+    // à compléter
+    return true;
+}
+
diff --git a/source_codes/arbres_binaires/bin_tree_part.h b/source_codes/arbres_binaires/bin_tree_part.h
new file mode 100644
index 0000000000000000000000000000000000000000..54e846d083756d121aa5f92d22fe05eaabea3542
--- /dev/null
+++ b/source_codes/arbres_binaires/bin_tree_part.h
@@ -0,0 +1,23 @@
+#ifndef BIN_TREE_H
+#define BIN_TREE_H
+
+#include <stdbool.h>
+
+// Structure pour un arbre binaire
+typedef int cle;
+typedef struct _node {
+    cle key;
+    struct _node *child[2];
+} node;
+typedef node *arbre;
+
+// Fonctionnalités pour un arbre binaire ordonné
+bool arbre_is_empty(arbre tree);
+bool arbre_search(arbre tree, cle c);
+bool arbre_insert(arbre *tree, cle c);
+bool arbre_delete(arbre *tree, cle c);
+void arbre_print(arbre tree, int N);
+int arbre_depth(arbre tree);
+int arbre_size(arbre tree);
+#endif
+
diff --git a/source_codes/arbres_binaires/main.c b/source_codes/arbres_binaires/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..6bc9e93e51b4f9bf1c599162ab07dd0a4c0e0fd8
--- /dev/null
+++ b/source_codes/arbres_binaires/main.c
@@ -0,0 +1,24 @@
+#include "bin_tree.h"
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void main() {
+    bool b;
+    int val;
+    arbre tree = NULL;
+    arbre_print(tree, 1);
+    do {
+        printf("insert val = ");
+        scanf("%d", &val);
+        b = arbre_insert(tree, val);
+        arbre_print(tree, 1);
+    } while (b);
+    node *nd;
+    do {
+        printf("delete val = ");
+        scanf("%d", &val);
+        b = arbre_delete(&tree, val);
+        arbre_print(tree, 1);
+    } while (NULL != tree);
+}
diff --git a/source_codes/arbres_binaires/tree_search.c b/source_codes/arbres_binaires/tree_search.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac4933fbde23d88d58e8f4b54de48e7e782c8ac5
--- /dev/null
+++ b/source_codes/arbres_binaires/tree_search.c
@@ -0,0 +1,31 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef int cle;
+typedef struct _node {
+    cle key;
+    struct _node *gauche;
+    struct _node *droite;
+} node;
+typedef node *arbre;
+
+arbre search(cle X, arbre tree) {
+    bool success  = false;
+    arbre courant = tree;
+    while (NULL != courant && !success) {
+        if (courant->key > X) {
+            courant = courant->gauche;
+        } else if (courant->key < X) {
+            courant = courant->droite;
+        } else {
+            success = true;
+        }
+    }
+    return courant;
+}
+
+void main() {
+    arbre tree;
+    arbre t = search(15, tree);
+}
diff --git a/source_codes/sorting/quicksort/.gitignore b/source_codes/sorting/quicksort/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b180f6c3fb9bf71cafaccf0e4b07f44ac9bb9b52
--- /dev/null
+++ b/source_codes/sorting/quicksort/.gitignore
@@ -0,0 +1,2 @@
+quicksort
+quicksort_part
diff --git a/source_codes/sorting/quicksort/Makefile b/source_codes/sorting/quicksort/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..927fce8eaec2e3f81c8804eb06c2e92709dbbf86
--- /dev/null
+++ b/source_codes/sorting/quicksort/Makefile
@@ -0,0 +1,21 @@
+CC:=gcc
+# SAN:=-fsanitize=address
+CFLAGS:=-Wall -Wextra -pedantic -g $(SAN)
+LDFLAGS:=-lm $(SAN)
+
+all: quicksort quicksort_part 
+
+quicksort: quicksort.c 
+	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+quicksort_part: quicksort_part.c 
+	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+	@echo $@ >> .gitignore
+
+
+.PHONY: clean all
+
+clean:
+	rm -f *.o quicksort_part quicksort .gitignore
+
diff --git a/source_codes/sorting/quicksort/quicksort.c b/source_codes/sorting/quicksort/quicksort.c
new file mode 100644
index 0000000000000000000000000000000000000000..af95cb590c2c039a5612fabeb7ef7e5df081f3d2
--- /dev/null
+++ b/source_codes/sorting/quicksort/quicksort.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+
+void print(int size,int tab[size]) {
+   for (int i=0;i<size;i++) {
+      printf("%d ",tab[i]);
+   }
+}
+
+void random_tab(int size,int tab[size],int inf,int sup) {
+   assert(sup > inf);
+   for (int i=0;i<size;i++) {
+      tab[i] = inf+rand()%(sup-inf);
+   }
+}
+
+void swap(int* p_a,int* p_b) { 
+   int tmp = *p_a;
+   *p_a = *p_b;
+   *p_b = tmp;
+}
+
+int partition(int size,int array[size],int first,int last) {
+   int pivot = array[last];
+   int i = first-1,j = last;
+   do {
+      do {
+         i++;
+      } while (array[i] < pivot && i<j);
+      do {
+         j--;
+      } while(array[j] > pivot && i<j);
+      if (j>i) {
+         swap(&array[i],&array[j]);
+      }
+   } while (j > i);
+   swap(&array[i],&array[last]);
+   return i;
+}
+
+void quicksort(int size,int array[size],int first,int last) {
+   if (first < last) {
+      int midpoint = partition(size,array,first,last);
+      if (first < midpoint-1) {
+         quicksort(size,array,first,midpoint-1);
+      }
+      if (midpoint+1 < last) {
+         quicksort(size,array,midpoint+1,last);
+      }
+   }
+}
+
+void test_ordre(int size,int array[size]) {
+   for (int i=0;i<size-1;i++) {
+      if (array[i] > array[i+1]) {
+         printf("erreur");
+         return;
+      }
+   }
+   printf("ok");
+}
+
+int main(int argc,char** argv) {
+   if (2 != argc) {
+      return 1;
+   }
+   int size = atoi(argv[1]);
+   int seed = atoi(argv[2]);
+   srand(seed);
+   int* res = malloc(size*sizeof(int));
+   for (int k=0;k<20;k++) {
+      random_tab(size,res,0,100);
+      print(size,res);
+      printf("\n");
+      quicksort(size,res,0,size-1);
+      print(size,res);
+      test_ordre(size,res);
+      printf("\n================\n");
+   }
+}
+
diff --git a/source_codes/sorting/quicksort/quicksort_part.c b/source_codes/sorting/quicksort/quicksort_part.c
new file mode 100644
index 0000000000000000000000000000000000000000..67b79b7b790de4e0f71f99465cfc445891c7d621
--- /dev/null
+++ b/source_codes/sorting/quicksort/quicksort_part.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+void print(int size,int tab[size]) {
+   for (int i=0;i<size;i++) {
+      printf("%d ",tab[i]);
+   }
+   printf("\n");
+}
+
+void random_tab(int size,int tab[size],int inf,int sup) {
+   for (int i=0;i<size;i++) {
+      tab[i] = inf+rand()%(sup-inf);
+   }
+}
+
+void swap(int* p_a,int* p_b) { 
+   int tmp = *p_a;
+   *p_a = *p_b;
+   *p_b = tmp;
+}
+
+// Partition du tableau <array> autour d'une valeur pivot:
+// compléter le code
+int partition(int size,int array[size],int first,int last) {
+   int pivot = array[last];
+   int i = first-1,j = last;
+   do {
+      // à compléter pour <i>: do {...} while (...);
+      // à compléter pour <j>: do {...} while (...);
+      // à compléter: échanger cases <i> et <j> du tableau <array>
+   } while (j > i);
+   // à compléter: échanger cases <i> et <last> du tableau <array>
+   return i;
+}
+
+// Tri rapide récursif
+void quicksort(int size,int array[size],int first,int last) {
+   if (first < last) {
+      int midpoint = partition(size,array,first,last);
+      if (first < midpoint-1) {
+         quicksort(size,array,first,midpoint-1);
+      }
+      if (midpoint+1 < last) {
+         quicksort(size,array,midpoint+1,last);
+      }
+   }
+}
+
+// Test si le tableau <array> est ordonné croissant
+void test_ordre(int size,int array[size]) {
+   for (int i=0;i<size-1;i++) { 
+      if (array[i] > array[i+1]) {
+         printf("erreur");
+         return;
+      }
+   }
+   printf("ok");
+}
+
+int main(int argc,char** argv) {
+   if (2 != argc) {
+      return 1;
+   }
+   int size = atoi(argv[1]);
+   int seed = atoi(argv[2]);
+   srand(seed);
+   int* res = (int*)malloc(size*sizeof(int));
+   for (int k=0;k<20;k++) {
+      random_tab(size,res,0,100);
+      print(size,res);
+      quicksort(size,res,0,size-1);
+      print(size,res);
+      test_ordre(size,res);
+      printf("\n================\n");
+   }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+