diff --git a/Progression.md b/Progression.md
index 10373ef..80dee10 100644
--- a/Progression.md
+++ b/Progression.md
@@ -5,7 +5,8 @@
| 2 - b | Diviser pour régner : tri fusion, dichotomie récursive | Exercices diviser pour régner |
| 3 - a | POO : classes, attributs, méthodes, encapsulation | TP Pokémon |
| 3 - b | Paradigmes : fonctionnel, impératif, orienté objet | TP SpotifyWrapped |
-| 4 | Structures linéaires : Pile, File — implémentation et usages | TP Pile, TP File, TP Navigateur |
+| 4 - a | Structures linéaires : Listes chaînées — maillon, insertion, suppression, récursivité | TP Playlist |
+| 4 - b | Structures linéaires : Pile, File — implémentation et usages | TP Pile, TP File, TP Navigateur |
| 5 - a | Bases de données : modèle relationnel, conception, clés | TP StreamFlix |
| 5 - b | SQL : requêtes, jointures, agrégation | TP Streaming Musical |
| 6 | Arbres : arbres binaires, ABR, parcours, applications | TP Livre Dont Vous Êtes le Héros, TP Recommandation |
diff --git a/Structures_lineaires/Listes_chainees/EXERCICES.md b/Structures_lineaires/Listes_chainees/EXERCICES.md
new file mode 100644
index 0000000..657b2b5
--- /dev/null
+++ b/Structures_lineaires/Listes_chainees/EXERCICES.md
@@ -0,0 +1,101 @@
+# Exercices — Listes chaînées
+
+---
+
+## Exercice 1 : Comprendre les maillons
+
+On dispose du code suivant :
+
+```python
+class Maillon:
+ def __init__(self, valeur, suivant=None):
+ self.valeur = valeur
+ self.suivant = suivant
+
+m3 = Maillon(30)
+m2 = Maillon(20, m3)
+m1 = Maillon(10, m2)
+```
+
+1. Représenter schématiquement la liste chaînée obtenue (avec les flèches).
+2. Quelle est la valeur de `m1.suivant.valeur` ?
+3. Quelle est la valeur de `m1.suivant.suivant.valeur` ?
+4. Que vaut `m3.suivant` ?
+
+---
+
+## Exercice 2 : Parcourir une liste
+
+On dispose d'une liste chaînée `l` dont la tête pointe vers `10 → 20 → 30 → 40 → None`.
+
+```python
+def afficher(liste):
+ courant = liste.tete
+ while courant is not None:
+ print(courant.valeur)
+ courant = courant.suivant
+```
+
+1. Dérouler manuellement l'exécution de `afficher(l)` : quelle est la valeur de `courant` à chaque tour de boucle ?
+2. Combien de fois la boucle s'exécute-t-elle ?
+3. Modifier la fonction pour qu'elle affiche les valeurs séparées par ` → ` sur une seule ligne (comme dans le cours).
+
+---
+
+## Exercice 3 : Opérations de base
+
+Implémenter les méthodes suivantes dans la classe `ListeChainee` :
+
+1. `inserer_en_queue(self, valeur)` → ajoute un maillon à la fin de la liste.
+ *Indication : parcourir jusqu'au dernier maillon, puis modifier son `.suivant`.*
+
+2. `supprimer_valeur(self, valeur)` → supprime le premier maillon contenant `valeur`.
+ *Cas particuliers : valeur en tête, valeur absente.*
+
+3. `nieme(self, n)` → renvoie la valeur du n-ième maillon (indice 0 = tête).
+ *Lever une `IndexError` si n est hors bornes.*
+
+---
+
+## Exercice 4 : Complexité
+
+Pour une liste chaînée de longueur n, indiquer la complexité (O(1) ou O(n)) des opérations suivantes et justifier :
+
+| Opération | Complexité | Justification |
+|-----------|------------|---------------|
+| Insérer en tête | | |
+| Insérer en queue | | |
+| Supprimer en tête | | |
+| Accéder au n-ième élément | | |
+| Rechercher une valeur | | |
+
+---
+
+## Exercice 5 : Version récursive
+
+1. Écrire la fonction récursive `longueur_rec(maillon)` qui renvoie le nombre de maillons à partir de `maillon`.
+
+2. Écrire la fonction récursive `rechercher_rec(maillon, valeur)` qui renvoie `True` si `valeur` est présente, `False` sinon.
+
+3. Écrire la fonction récursive `renverser(maillon)` qui renvoie une nouvelle liste chaînée dont les éléments sont dans l'ordre inverse.
+ *Exemple : `10 → 20 → 30 → None` devient `30 → 20 → 10 → None`.*
+
+---
+
+## Exercice 6 : Implémenter une Pile avec une liste chaînée
+
+En utilisant `Maillon`, implémenter la classe `Pile` avec les méthodes :
+- `empiler(valeur)` → ajoute au sommet
+- `depiler()` → retire et renvoie le sommet
+- `sommet()` → consulte le sommet sans le retirer
+- `est_vide()` → renvoie `True` si la pile est vide
+
+Tester avec : empiler 1, 2, 3, puis dépiler jusqu'à vide.
+
+---
+
+Auteur : Florian Mathieu
+
+Licence CC BY NC
+
+
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.
diff --git a/Structures_lineaires/Listes_chainees/README.md b/Structures_lineaires/Listes_chainees/README.md
new file mode 100644
index 0000000..bf4e9e0
--- /dev/null
+++ b/Structures_lineaires/Listes_chainees/README.md
@@ -0,0 +1,172 @@
+# Listes chaînées
+
+> Un tableau Python (`list`) permet d'accéder à n'importe quel élément en O(1) grâce aux indices — mais insérer ou supprimer un élément au milieu déplace tous ceux qui suivent. La liste chaînée adopte une autre approche : chaque élément connaît son successeur, et seuls les liens changent lors d'une modification.
+
+## 1. Limite des tableaux pour certains usages
+
+```python
+t = [1, 2, 3, 4, 5]
+t.insert(2, 99) # insère 99 à l'indice 2
+# → [1, 2, 99, 3, 4, 5]
+# Python a dû décaler 3, 4, 5 vers la droite : O(n)
+```
+
+Pour un tableau de 10 millions d'éléments, une insertion au début déplace 10 millions de valeurs. La liste chaînée résout ce problème : insérer en tête est toujours O(1).
+
+---
+
+## 2. Le maillon
+
+L'unité de base d'une liste chaînée est un **maillon** (ou cellule, ou nœud). Il contient :
+- une **valeur** (la donnée stockée)
+- un **pointeur** vers le maillon suivant (ou `None` si c'est le dernier)
+
+```python
+class Maillon:
+ def __init__(self, valeur, suivant=None):
+ self.valeur = valeur
+ self.suivant = suivant
+```
+
+On peut enchaîner des maillons manuellement :
+
+```python
+m3 = Maillon(30)
+m2 = Maillon(20, m3)
+m1 = Maillon(10, m2)
+# m1 → m2 → m3 → None
+# 10 → 20 → 30 → None
+```
+
+---
+
+## 3. La classe ListeChainee
+
+On encapsule la liste dans une classe qui mémorise uniquement la **tête** (premier maillon) :
+
+```python
+class ListeChainee:
+ def __init__(self):
+ self.tete = None # liste vide
+
+ def est_vide(self):
+ return self.tete is None
+```
+
+### Insérer en tête
+
+```python
+def inserer_en_tete(self, valeur):
+ nouveau = Maillon(valeur, self.tete)
+ self.tete = nouveau
+```
+
+```
+Avant : tete → [20] → [30] → None
+Après : tete → [10] → [20] → [30] → None
+```
+
+### Supprimer en tête
+
+```python
+def supprimer_en_tete(self):
+ if self.est_vide():
+ raise IndexError("Liste vide")
+ valeur = self.tete.valeur
+ self.tete = self.tete.suivant
+ return valeur
+```
+
+### Afficher la liste
+
+```python
+def afficher(self):
+ courant = self.tete
+ elements = []
+ while courant is not None:
+ elements.append(str(courant.valeur))
+ courant = courant.suivant
+ print(" → ".join(elements) + " → None")
+```
+
+```python
+l = ListeChainee()
+l.inserer_en_tete(30)
+l.inserer_en_tete(20)
+l.inserer_en_tete(10)
+l.afficher()
+# 10 → 20 → 30 → None
+```
+
+### Longueur
+
+```python
+def longueur(self):
+ courant = self.tete
+ n = 0
+ while courant is not None:
+ n += 1
+ courant = courant.suivant
+ return n
+```
+
+### Rechercher
+
+```python
+def rechercher(self, valeur):
+ courant = self.tete
+ while courant is not None:
+ if courant.valeur == valeur:
+ return True
+ courant = courant.suivant
+ return False
+```
+
+---
+
+## 4. Structure récursive
+
+Une liste chaînée est naturellement **récursive** :
+- soit elle est **vide**
+- soit elle est un **maillon** (tête) suivi d'une **liste chaînée** (queue)
+
+On peut écrire la longueur de manière récursive :
+
+```python
+def longueur_rec(maillon):
+ if maillon is None:
+ return 0
+ return 1 + longueur_rec(maillon.suivant)
+```
+
+Cette vision récursive ("tête + queue") est la même qu'on retrouve dans les arbres (chapitre Arbres).
+
+---
+
+## 5. Liste chaînée vs tableau Python
+
+| | Tableau Python (`list`) | Liste chaînée |
+|---|---|---|
+| Accès par indice | O(1) | O(n) |
+| Insertion en tête | O(n) | O(1) |
+| Suppression en tête | O(n) | O(1) |
+| Mémoire | Contiguë | Dispersée (maillons) |
+| Usage naturel | Accès aléatoire | Insertion/suppression fréquentes |
+
+---
+
+## 6. Lien avec Pile et File
+
+Une **pile** (LIFO) s'implémente naturellement avec une liste chaînée : `inserer_en_tete` = empiler, `supprimer_en_tete` = dépiler.
+
+Une **file** (FIFO) s'implémente avec deux pointeurs : tête pour supprimer, queue pour insérer.
+
+C'est précisément ce que vous allez implémenter dans le chapitre suivant.
+
+---
+
+Auteur : Florian Mathieu
+
+Licence CC BY NC
+
+
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.
diff --git a/Structures_lineaires/Listes_chainees/TP_Playlist.md b/Structures_lineaires/Listes_chainees/TP_Playlist.md
new file mode 100644
index 0000000..099ffff
--- /dev/null
+++ b/Structures_lineaires/Listes_chainees/TP_Playlist.md
@@ -0,0 +1,139 @@
+# TP — Playlist musicale
+
+> Implémenter une playlist sous forme de liste chaînée : ajouter des titres, en retirer, naviguer d'un morceau à l'autre — et comprendre pourquoi cette structure est naturellement adaptée à ce type d'usage.
+
+---
+
+## Contexte
+
+Un lecteur de musique gère une **playlist** : une séquence de titres qu'on peut modifier en cours de route (ajouter un titre, supprimer un titre, passer au suivant). Un tableau Python serait peu adapté à ces insertions et suppressions fréquentes — la liste chaînée l'est beaucoup mieux.
+
+---
+
+## Partie 1 : La structure de base
+
+### Étape 1 — Le maillon
+
+Implémenter la classe `Titre` qui représente un maillon de la playlist :
+
+```python
+class Titre:
+ def __init__(self, nom, artiste, suivant=None):
+ self.nom = nom
+ self.artiste = artiste
+ self.suivant = suivant
+
+ def __str__(self):
+ return f"{self.nom} — {self.artiste}"
+```
+
+### Étape 2 — La playlist
+
+Implémenter la classe `Playlist` :
+
+```python
+class Playlist:
+ def __init__(self, nom):
+ self.nom = nom
+ self.tete = None
+ self.courant = None # titre en cours de lecture
+```
+
+---
+
+## Partie 2 : Gestion de la playlist
+
+### Question 1
+
+Implémenter `ajouter_en_tete(self, nom, artiste)` → ajoute un titre au début de la playlist.
+
+### Question 2
+
+Implémenter `ajouter_en_queue(self, nom, artiste)` → ajoute un titre à la fin.
+
+*Quelle méthode est en O(1) ? Laquelle est en O(n) ? Pourquoi ?*
+
+### Question 3
+
+Implémenter `supprimer(self, nom)` → supprime le premier titre dont le nom correspond.
+Gérer le cas où le titre est en tête, en milieu, ou absent.
+
+### Question 4
+
+Implémenter `afficher(self)` → affiche tous les titres de la playlist dans l'ordre, numérotés.
+
+```
+Playlist : "Ma playlist"
+1. Bohemian Rhapsody — Queen
+2. Blinding Lights — The Weeknd
+3. Starboy — The Weeknd
+```
+
+---
+
+## Partie 3 : Lecture
+
+### Question 5
+
+Implémenter `lecture_suivante(self)` → passe au titre suivant dans la playlist.
+- Si `courant` est `None`, commencer par la tête.
+- Si `courant` est le dernier titre, retourner au début (liste circulaire).
+
+### Question 6
+
+Implémenter `lire(self)` → affiche le titre en cours de lecture.
+
+```
+♪ En cours : Bohemian Rhapsody — Queen
+```
+
+---
+
+## Partie 4 : Fonctionnalités avancées
+
+### Question 7
+
+Implémenter `longueur(self)` → renvoie le nombre de titres.
+
+### Question 8
+
+Implémenter `rechercher(self, artiste)` → renvoie la liste de tous les titres d'un artiste donné.
+
+### Question 9 — Défi
+
+Implémenter `melanger(self)` → réorganise les titres dans un ordre aléatoire.
+
+*Indication : convertir la liste chaînée en tableau Python, mélanger avec `random.shuffle`, reconstruire la liste chaînée.*
+
+---
+
+## Partie 5 : Test complet
+
+```python
+p = Playlist("Ma playlist")
+p.ajouter_en_queue("Bohemian Rhapsody", "Queen")
+p.ajouter_en_queue("Blinding Lights", "The Weeknd")
+p.ajouter_en_queue("Starboy", "The Weeknd")
+p.ajouter_en_tete("Hotel California", "Eagles")
+
+p.afficher()
+print(f"Longueur : {p.longueur()}")
+
+p.lecture_suivante()
+p.lire()
+p.lecture_suivante()
+p.lire()
+
+p.supprimer("Starboy")
+p.afficher()
+
+print(p.rechercher("The Weeknd"))
+```
+
+---
+
+Auteur : Florian Mathieu
+
+Licence CC BY NC
+
+
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.
diff --git a/Pile_File/Images/File.png b/Structures_lineaires/Pile_File/Images/File.png
similarity index 100%
rename from Pile_File/Images/File.png
rename to Structures_lineaires/Pile_File/Images/File.png
diff --git a/Pile_File/Images/File_td.png b/Structures_lineaires/Pile_File/Images/File_td.png
similarity index 100%
rename from Pile_File/Images/File_td.png
rename to Structures_lineaires/Pile_File/Images/File_td.png
diff --git a/Pile_File/Images/Pile.odg b/Structures_lineaires/Pile_File/Images/Pile.odg
similarity index 100%
rename from Pile_File/Images/Pile.odg
rename to Structures_lineaires/Pile_File/Images/Pile.odg
diff --git a/Pile_File/Images/Pile.png b/Structures_lineaires/Pile_File/Images/Pile.png
similarity index 100%
rename from Pile_File/Images/Pile.png
rename to Structures_lineaires/Pile_File/Images/Pile.png
diff --git a/Pile_File/Images/Pile_td.png b/Structures_lineaires/Pile_File/Images/Pile_td.png
similarity index 100%
rename from Pile_File/Images/Pile_td.png
rename to Structures_lineaires/Pile_File/Images/Pile_td.png
diff --git a/Pile_File/Images/bo_1.png b/Structures_lineaires/Pile_File/Images/bo_1.png
similarity index 100%
rename from Pile_File/Images/bo_1.png
rename to Structures_lineaires/Pile_File/Images/bo_1.png
diff --git a/Pile_File/Images/bo_2.png b/Structures_lineaires/Pile_File/Images/bo_2.png
similarity index 100%
rename from Pile_File/Images/bo_2.png
rename to Structures_lineaires/Pile_File/Images/bo_2.png
diff --git a/Pile_File/README.md b/Structures_lineaires/Pile_File/README.md
similarity index 100%
rename from Pile_File/README.md
rename to Structures_lineaires/Pile_File/README.md
diff --git a/Pile_File/TD/Corrige_TD_Pile_File.md b/Structures_lineaires/Pile_File/TD/Corrige_TD_Pile_File.md
similarity index 100%
rename from Pile_File/TD/Corrige_TD_Pile_File.md
rename to Structures_lineaires/Pile_File/TD/Corrige_TD_Pile_File.md
diff --git a/Pile_File/TD/TD_Pile_File.md b/Structures_lineaires/Pile_File/TD/TD_Pile_File.md
similarity index 100%
rename from Pile_File/TD/TD_Pile_File.md
rename to Structures_lineaires/Pile_File/TD/TD_Pile_File.md
diff --git a/Pile_File/TP/Bataille_correction.py b/Structures_lineaires/Pile_File/TP/Bataille_correction.py
similarity index 100%
rename from Pile_File/TP/Bataille_correction.py
rename to Structures_lineaires/Pile_File/TP/Bataille_correction.py
diff --git a/Pile_File/TP/Corrige_TP_Navigateur.py b/Structures_lineaires/Pile_File/TP/Corrige_TP_Navigateur.py
similarity index 100%
rename from Pile_File/TP/Corrige_TP_Navigateur.py
rename to Structures_lineaires/Pile_File/TP/Corrige_TP_Navigateur.py
diff --git a/Pile_File/TP/File.py b/Structures_lineaires/Pile_File/TP/File.py
similarity index 100%
rename from Pile_File/TP/File.py
rename to Structures_lineaires/Pile_File/TP/File.py
diff --git a/Pile_File/TP/TP_File.md b/Structures_lineaires/Pile_File/TP/TP_File.md
similarity index 100%
rename from Pile_File/TP/TP_File.md
rename to Structures_lineaires/Pile_File/TP/TP_File.md
diff --git a/Pile_File/TP/TP_Navigateur.md b/Structures_lineaires/Pile_File/TP/TP_Navigateur.md
similarity index 100%
rename from Pile_File/TP/TP_Navigateur.md
rename to Structures_lineaires/Pile_File/TP/TP_Navigateur.md
diff --git a/Pile_File/TP/TP_Pile.md b/Structures_lineaires/Pile_File/TP/TP_Pile.md
similarity index 100%
rename from Pile_File/TP/TP_Pile.md
rename to Structures_lineaires/Pile_File/TP/TP_Pile.md
diff --git a/Pile_File/TP/TP_Pile_correction.py b/Structures_lineaires/Pile_File/TP/TP_Pile_correction.py
similarity index 100%
rename from Pile_File/TP/TP_Pile_correction.py
rename to Structures_lineaires/Pile_File/TP/TP_Pile_correction.py
diff --git a/Pile_File/TP/carte_eleve.py b/Structures_lineaires/Pile_File/TP/carte_eleve.py
similarity index 100%
rename from Pile_File/TP/carte_eleve.py
rename to Structures_lineaires/Pile_File/TP/carte_eleve.py
diff --git a/Structures_lineaires/README.md b/Structures_lineaires/README.md
new file mode 100644
index 0000000..c705dd1
--- /dev/null
+++ b/Structures_lineaires/README.md
@@ -0,0 +1,30 @@
+# Structures de données linéaires
+
+> Un tableau Python permet d'accéder instantanément à n'importe quel élément par son indice. Mais certains problèmes demandent des structures plus souples : ajouter ou supprimer des éléments sans déplacer tout le reste, ou imposer un ordre d'accès strict. C'est l'objet de ce chapitre.
+
+## Programme
+
+
+
+## Les trois structures au programme
+
+| Structure | Accès | Insertion | Suppression | Usage typique |
+|-----------|-------|-----------|-------------|---------------|
+| **Liste chaînée** | Séquentiel | En tête : O(1) | En tête : O(1) | Structure de base, implémente pile et file |
+| **Pile** (stack) | Dernier entré (LIFO) | En tête : O(1) | En tête : O(1) | Appels de fonctions, annulation (Ctrl+Z) |
+| **File** (queue) | Premier entré (FIFO) | En queue : O(1) | En tête : O(1) | File d'attente, BFS, impression |
+
+## Ressources
+
+| Fichier | Description |
+|---------|-------------|
+| [Listes chaînées](Listes_chainees/README.md) | La brique de base : maillon, insertion, suppression, parcours |
+| [Piles et Files](Pile_File/README.md) | Deux structures aux contraintes d'accès strictes |
+
+---
+
+Auteur : Florian Mathieu
+
+Licence CC BY NC
+
+
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.