diff --git a/slides/cours_7.md b/slides/cours_7.md
index 12e9665bac2f5dd2021fd695b7d5eb2c2d8b6709..92b1d2aa93461229ede5e0957bc21e05c6f83521 100644
--- a/slides/cours_7.md
+++ b/slides/cours_7.md
@@ -1,6 +1,8 @@
 ---
 title: "Récursion et tris"
-date: "2022-11-16"
+date: "2023-11-07"
+header-includes: |
+    \usepackage{xcolor}
 ---
 
 # Exponentiation rapide ou indienne (1/4)
@@ -88,6 +90,377 @@ double pow(double x, int n) {
 }
 ```
 
+# Tri par base (radix sort)
+
+* N'utilise pas la notion de comparaisons, mais celle de classement successif dans des catégories (buckets).
+* Pour simplifier
+    * Tri de nombre entiers dans un tableau.
+    * On considère que des nombres $\ge 0$ (sans perte de généralité).
+    * On considère ensuite la représentation binaire de ces nombres.
+
+# Principe de l'algorithme
+
+1. On considère le bit le moins significatif.
+2. On parcourt une 1ère fois le tableau et on place à la suite dans un 2ème tableau les éléments dont le bit est 0;
+   puis on répète l'opération 2 pour les éléments dont le bit est 1.
+3. On répète l'étape 2 en regardant le bit suivant et en permutant le rôle des deux tableaux.
+
+On utilise donc deux tableaux pour réaliser ce tri.
+A noter qu'à chaque étape, l'ordre des éléments dont le bit est à 0 (respectivement à 1) reste identique dans le 2ème tableau par rapport au 1er tableau.
+
+# Illustration sur un exemple (1/6)
+
+Soit la liste de nombre entier: 
+
+|  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
+|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+|  5  | -5  |  1  |  6  |  4  |  -6 |  2  | -9  |  2  |
+
+Le plus petit élément est -9. On commence donc par décaler les valeurs de 9.
+
+|  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
+|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+| 14  |  4  |  10 |  15 |  13 |  3  |  11 |  0  |  11 |
+
+# Illustration sur un exemple (2/6)
+
+* Écrivons les éléments en représentation binaire.
+* La valeur maximale est 15, on a besoin de 4 bits.
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| 14  |  4  |  10 |  15 |  13 |  3  |  11 |  0  |  11 |
+| 1110 | 0100 | 1010 | 1111 | 1101 | 0011 | 1011 | 0000 | 1011 |
+
+# Illustration sur un exemple (3/6)
+
+* On considère le bit de poids faible
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| 111**0** | 010**0** | 101**0** | 111**1** | 110**1** | 001**1** | 101**1** | 000**0** | 101**1** |
+
+. . .
+
+* On obtient le tableau:
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| 111\textcolor{red}{0} | 010\textcolor{red}{0} | 101\textcolor{red}{0} | 111\textcolor{green}{1} | 110\textcolor{green}{1} | 001\textcolor{green}{1} | 101\textcolor{green}{1} | 000\textcolor{red}{0} | 101\textcolor{green}{1} |
+| \textcolor{red}{1110} | \textcolor{red}{0100} | \textcolor{red}{1010} | \textcolor{red}{0000} | \textcolor{green}{1111} | \textcolor{green}{1101} | \textcolor{green}{0011} | \textcolor{green}{1011} | \textcolor{green}{1011} |
+
+# Illustration sur un exemple (4/6)
+
+* On passe au 2ème bit et on obtient le tableau:
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| 11\textcolor{green}{1}0 | 01\textcolor{red}{0}0 | 10\textcolor{green}{1}0 | 00\textcolor{red}{0}0 | 11\textcolor{green}{1}1 | 11\textcolor{red}{0}1 | 00\textcolor{green}{1}1 | 10\textcolor{green}{1}1 | 10\textcolor{green}{1}1 |
+| \textcolor{red}{0100} | \textcolor{red}{0000} | \textcolor{red}{1101} | \textcolor{green}{1110} | \textcolor{green}{1010} | \textcolor{green}{1111} | \textcolor{green}{0011} | \textcolor{green}{1011} | \textcolor{green}{1011} |
+
+. . .
+
+* On passe au 3ème bit et on obtient le tableau:
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| 0\textcolor{green}{1}00 | 0\textcolor{red}{0}00 | 1\textcolor{green}{1}01 | 1\textcolor{green}{1}10 | 1\textcolor{red}{0}10 | 1\textcolor{green}{1}11 | 0\textcolor{red}{0}11 | 1\textcolor{red}{0}11 | 1\textcolor{red}{0}11 |
+| \textcolor{red}{0000} | \textcolor{red}{1010} | \textcolor{red}{0011} | \textcolor{red}{1011} | \textcolor{red}{1011} | \textcolor{green}{0100} | \textcolor{green}{1101} | \textcolor{green}{1110} | \textcolor{green}{1111} |
+
+
+# Illustration sur un exemple (5/6)   
+
+4. On passe au dernier bit et on obtient le tableau final:
+
+|   0  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |
+|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
+| \textcolor{red}{0}000 | \textcolor{green}{1}010 | \textcolor{red}{0}011 | \textcolor{green}{1}011 | \textcolor{green}{1}011 | \textcolor{red}{0}100 | \textcolor{green}{1}101 | \textcolor{green}{1}110 | \textcolor{green}{1}111 |
+| \textcolor{red}{0000} | \textcolor{red}{0011} | \textcolor{red}{0100} | \textcolor{green}{1010} | \textcolor{green}{1011} | \textcolor{green}{1011} | \textcolor{green}{1101} | \textcolor{green}{1110} | \textcolor{green}{1111} |
+
+. . .
+
+* En revenant à la représentation décimale, on a le tableau trié:
+
+|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |
+|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
+|  0 |  3 |  4 | 10 | 11 | 11 | 13 | 14 | 15 |
+
+# Illustration sur un exemple (6/6)   
+
+* Pour revenir aux valeurs initiales, il faut décaler de 9 dans l'autre sens.
+
+|  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
+|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+| -9  | -6  | -5  |  1  |  2  |  2  |  4  |  5  |  6  |
+
+. . .
+
+* The end.
+
+
+# Pseudo-code
+
+```python
+rien radix_sort(entier taille, entier tab[taille]):
+# initialisation
+    entier val_min = valeur_min(taille, tab)
+    entier val_max = valeur_max(taille, tab)
+    decaler(taille, tab, val_min)
+    entier nb_bits = nombre_de_bits(val_max - val_min)
+# algo
+    entier tab_tmp[taille]
+    pour pos de 0 à nb_bits:
+        alveole_0(taille, tab, tab_tmp, pos) # 0 -> taille
+        alveole_1(taille, tab, tab_tmp, pos) # taille -> 0
+        echanger(tab, tab_tmp)
+# post-traitement
+    decaler(taille, tab, -val_min)
+```
+<!-- ```C
+void radix_sort(int size,int tab[size]) {
+   int val_min = tab[index_min(size,tab)];
+   int val_max = tab[index_max(size,tab)];
+
+   decaler(size, tab,val_min);
+   int nb_bits = get_nb_bits(val_max-val_min);
+
+   int tab_tmp[size];
+   for (int pos=0;pos<nb_bits;pos++) {
+      bucket_0(size,tab,tab_tmp,pos);
+      bucket_1(size,tab,tab_tmp,pos);
+      swap(tab,tab_tmp);
+   }
+   decaler(size,tab,-val_min);
+}
+``` -->
+
+# Un peu plus de détails (1/2)
+
+## La fonction `decaler()`
+
+```python
+rien decaler(entier taille, entier tab[taille], entier val):
+    pour i de 0 à taille-1:
+        taille[i] -= val
+```
+
+. . .
+
+## La fonction `echanger()`
+
+```python
+rien echanger(entier tab[], entier tab2[])
+# échanger les pointeurs vers les tableaux
+```
+
+# Un peu plus de détails (2/2)
+
+## La fonction `alveole_0()`
+
+```python
+rien alveole_0(entier taille, entier tab[taille], 
+               entier tab_tmp[taille], entier pos):
+    entier k = 0
+    pour i de 0 à taille-1:
+        si git(tab[i], pos):
+            tab_tmp[k] = tab[i]
+            k = k + 1
+```
+
+. . .
+
+## La fonction `alveole_1()`
+
+```python
+rien alveole_1(entier taille, entier tab[taille], 
+               entier tab_tmp[taille], entier pos):
+    # pareil que alveole 1 mais en partant de taille
+```
+
+<!-- ```C
+int index_min(int size,int tab[size],int i) {
+   //à compléter
+   return 0;
+}
+
+int index_max(int size,int tab[size],int i) {
+   //à compléter
+    return 0;
+}
+
+int get_bit(int x,int pos) {
+   //à compléter
+   return 0;
+}
+
+int get_nb_bits(int x) {
+   //à compléter
+   return 0;
+}
+
+void swap_ptr(int** a,int** b) {
+   //à compléter
+   return 0;
+}
+
+void bucket_0(int size,int* tab1,int* tab2,int pos) {
+   int k = 0;
+   for (int i = 0; i < size; i++) {
+      if (0 == get_bit(tab1[i], pos)) {
+         tab2[k] = tab1[i];
+         k += 1;
+      }
+   }
+}
+
+void bucket_1(int size,int* tab1,int* tab2,int pos) {
+   int k = size - 1;
+   for (int i = size - 1; i >= 0; i--) {
+      if (1 == get_bit(tab1[i], pos)) {
+         tab2[k] = tab1[i];
+         k -= 1;
+      }
+   }
+}
+
+void radix_sort(int size, int tab[size]) {
+   int val_min = tab[index_min(size,tab)];
+   int val_max = tab[index_max(size,tab)];
+   int nb_bits = get_nb_bits(val_max-val_min);
+   
+   int tab_tmp[size];     
+   int* tab1 = &tab[0];
+   int* tab2 = &tab_tmp[0];
+   // décalage des valeurs du tableau dans l'intervalle 0..val_max-val_min
+   for (int i=0; i < size; i++) {
+      tab1[i] -= val_min;
+   }
+   
+    for (int pos=0;pos<nb_bits;pos++) {
+        bucket_0(size, tab1, tab2, pos);
+        bucket_1(size, tab1, tab2, pos);
+        swap_ptr(&tab1, &tab2);
+    } 
+
+   // décalage inverse dans l'intervalle val_min..val_max
+   for (int i=0;i<size;i++) {
+      tab1[i] += val_min;
+   }
+   
+   if (tab1 != tab) {   
+      for (int i=0;i<size;i++) {
+         tab[i] = tab1[i];
+      }
+   }
+}
+``` -->
+
+<!-- # Complexité
+
+L'algorithme implémenté précédemment nécessite un certain nombre d'opérations lié à la taille du tableau.
+
+Voici une liste de parcours utilitaires de tableau:
+
+1. Recherche de la valeur minimum ```val_min```
+2. Recherche de la valeur maximum ```val_max```
+3. Décalage des valeurs dans l'intervalle ```0..val_max-val_min```
+4. Décalage inverse pour revenir dans l'intervalle ```val_min..val_max```
+5. Copie éventuelle du tableau temporaire dans le tableau originel
+
+On a donc un nombre de parcours fixe (4 ou 5) qui se font en $\mathcal{O}(N)$ où $N$ est la taille du tableau.
+
+La partie du tri à proprement parler est une boucle sur le nombre de bits *b* de ```val_min..val_max```.
+
+A chaque passage à travers la boucle, on parcourt 2 fois le tableau: la 1ère fois pour s'occuper des éléments dont le bit courant à 0; la 2ème pour ceux dont le bit courant est à 1.
+
+A noter que le nombre d'opérations est de l'ordre de *b*  pour la lecture d'un bit et constant pour la fonction ```swap_ptr()```.
+
+Ainsi, la complexité du tri par base est $\mathcal{O}(b\cdot N)$. -->
+
+# Tri par fusion (merge sort)
+
+* Tri par comparaison.
+* Idée: deux listes triées, sont fusionnées pour donner une liste triée plus longue.
+* Itérativement, on trie d'abord les paires de nombres, puis les groupes de 4 nombres, ensuite de 8, et ainsi de suite jusqu'à obtenir un tableau trié. 
+<!-- * On simplifie ici: le tableau a une longueur de puissance de 2. -->
+
+<!-- Pour son implémentation, le tri par fusion nécessite d'utiliser une zone temporaire de stockage des données de taille égale à celle de la liste de nombres à trier. On considère le cas du tri d'une liste de nombres entiers stockés dans un tableau. -->
+
+# Principe de l'algorithme
+
+* Soit `taille` la taille du tableau à trier.
+* Pour `i = 0` à `entier(\log_2(taille))-1`:
+    * Fusion des paires de sous-tableaux successifs de taille `2**i` (ou moins pour l'extrémité)
+
+. . .
+
+* Remarques: 
+    * Pour l'étape `i`, les sous-tableaux de taille `2**i` sont triés.
+    * La dernière paire de sous-tableaux peut être incomplète (vide ou avec moins que `2**i` éléments).
+
+# Exemple de tri par fusion
+
+* Soit la liste de nombres entiers stockés dans un tableau de taille 9: 
+
+|  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
+|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+|  5  | -5  |  1  | 6   |  4  |  -6 |  2  | -9  |  2  |
+
+. . .
+
+* Fusion des éléments successifs (ce qui revient à les mettre dans l'ordre):
+
+| étape |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
+|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+|   0   |  \textcolor{red}{5}  | \textcolor{green}{-5} |  \textcolor{red}{1}  | \textcolor{green}{6} |  \textcolor{red}{4}  | \textcolor{green}{-6} |  \textcolor{red}{2}  | \textcolor{green}{-9} |  \textcolor{red}{2}  |
+|   1   | \textcolor{red}{-5}  |  \textcolor{red}{5}  | \textcolor{green}{1} | \textcolor{green}{6} |  \textcolor{red}{-6} |  \textcolor{red}{4}  | \textcolor{green}{-9} | \textcolor{green}{2} |  \textcolor{red}{2}  |
+|   2   | \textcolor{red}{-5}  |  \textcolor{red}{1}  |  \textcolor{red}{5}  |  \textcolor{red}{6}  | \textcolor{green}{-9} | \textcolor{green}{-6} | \textcolor{green}{2}  | \textcolor{green}{4} |  \textcolor{red}{2}  |
+|   3   | \textcolor{red}{-9}  |  \textcolor{red}{-6} | \textcolor{red}{-5}  |  \textcolor{red}{1}  |  \textcolor{red}{2}  |  \textcolor{red}{4}  |  \textcolor{red}{5}  |  \textcolor{red}{6}  | \textcolor{green}{2} |
+|   4   | -9  |  -6 | -5  |  1  |  2  |  2  |  4  |  5  |  6  |
+
+# Pseudo-code
+
+```python
+rien tri_fusion(entier taille, entier tab[taille]) {
+    entier tab_tmp[taille];
+    entier nb_etapes = log_2(size) + 1; 
+    pour etape de 0 a nb_etapes - 1:
+        entier gauche = 0;
+        entier taille_tranche = 2**etape;
+        tant que (gauche < taille):
+            fusion(tab[gauche..gauche+taille_tranche-1], tab[gauche+taille_tranche..gauche+2*taille_tranche-1],
+                tab_tmp[gauche..gauche+2*taille_tranche-1]); #bornes incluses
+            gauche += 2*taille_tranche;
+        echanger(tab, tab_tmp);
+```
+
+# La fonction de fusion
+
+```python
+# hyp: tab_g et tab_d sont triés
+rien fuction(entier tab_g[], entier tab_d[], entier res[]):
+    entier g = taille(tab_g)
+    entier d = taille(tab_d)
+    entier i_g = 0, i_d = 0
+    pour i = 0 à g + d:
+        si tab_g[i_g] < tab[i_d]:
+            res[i] = tab_g[i_g]
+            i_g = i_g + 1
+        sinon:
+            res[i] = tab_g[i_d]
+            i_d = i_d + 1
+
+```
+
+<!-- ## Complexité
+L'algorithme présenté précédemment nécessite un certain nombre d'opérations lié à la taille $N$ du tableau.
+
+Il y a essentiellement $\log_2(N)$ étapes. 
+
+A chaque étape, le tableau est parcouru une fois avec un nombre constant effectué pour chacune des cases du tableau. En effet, l'opération de fusion implique de ne parcourir qu'une seule fois chacun des deux tableaux qu'on fusionne dans un 3ème tableau.
+
+Ainsi, la complexité du tri par fusion est $\mathcal{O}(N\cdot \log_2(N)$. -->
+
 # Tri rapide ou quicksort (1/8)
 
 ## Idée: algorithme `diviser pour régner` (`divide-and-conquer`)
@@ -265,8 +638,6 @@ int partition(int size, int array[size], int first, int last) {
 
 ```
 
-
-
 # Tri à bulle (1/4)
 
 ## Algorithme