diff --git a/TD02/INF-TC1-td02.ipynb b/TD02/INF-TC1-td02.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..092659048d6cc797ec369bdd6a055c5e4a1431c8
--- /dev/null
+++ b/TD02/INF-TC1-td02.ipynb
@@ -0,0 +1,1220 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "fab957ee",
+   "metadata": {},
+   "source": [
+    "NAME:"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4079279c",
+   "metadata": {},
+   "source": [
+    "# INF TC1 - TD2 (2h) - Structures de données"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "74d75def",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "42890ec6-251a-404c-a6f6-39c138db8650",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "### IMPORTANT A LIRE (SUR L'UTILISATION DE CE NOTEBOOK)\n",
+    "\n",
+    "Le but de votre travail est de répondre aux questions des exercices en **remplissant certaines cellules de ce notebook avec votre solution**. Ces cellules, une foit remplies et lancées au fur et à mesure de vos avancées, permettront de valider des tests écrits dans d'autres cellules de ce notebook. **Il est donc important de bien suivre les instructions et répondre aux questions dans l'ordre**, et ne pas changer le nom des fonctions et/ou les cellules. En particulier :\n",
+    "    \n",
+    "1) Répondez aux questions dans les cellules en dessous des questions.\n",
+    "\n",
+    "2) Votre code devra remplacer le texte suivant : \n",
+    "\n",
+    "```python\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()\n",
+    "```\n",
+    "\n",
+    "(vous pouvez effacer ces deux lignes quand vous les rencontrez mais ne modifiez pas les noms de fonctions sinon les tests ne marchent plus).\n",
+    "\n",
+    "3) Exécuter enfin les cellules dans leur ordre d'apparition, de haut en bas et si votre code est correct alors les tests (sous forme d'`assert` seront validés (ils ne lanceront pas d'exception du type `AssertionError` ). Vous pouvez lancer plusieurs fois la même cellule, cela ne pose pas de soucis.\n",
+    "    \n",
+    "4) Vous pouvez créer de nouvelles cellules comme bon vous semble.\n",
+    "\n",
+    "**En cas de problème, une solution est de relancer les cellules depuis le début du notebook une par une.** Pensez à bien sauvegarder ce notebook et ne pas le remplacer par un notebook qui a le même nom.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b692d4dd-6dbc-40e9-9c19-0b59e31e5eab",
+   "metadata": {},
+   "source": [
+    "## Objectif du TD\n",
+    "\n",
+    "Ce TD vous fera manipuler plusieurs structures de données standard en Python (listes, dictionnaires) mais également des structures avancées (piles, files tas) que vous allez créer au moyen de classes. Au final nous allons créer une méthode de tri efficace (tri par tas) et la comparer avec d'autres méthodes de tri de Python."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b6221ad1-379e-4e50-8c22-220994439b6d",
+   "metadata": {},
+   "source": [
+    "## Exercice 1 - Chargement et tri d'une liste\n",
+    "\n",
+    "Le but de cet exercice est de charger une liste de dictionnaires et réaliser des méthodes de tri. Vous disposez pour cela d'un fichier appelé [`etudiants.txt`](etudiants.txt) où chaque ligne contient des informations sur des étudiants d'un cour. Pour commencer nous allons réaliser des tris simples et les rendre de plus en plus complexes."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "985e2dd2-dc05-437c-b3f0-60696fe27e3f",
+   "metadata": {},
+   "source": [
+    "### Rappel : Tri de listes\n",
+    "\n",
+    "Avant de commencer quelques rappels sur les structures de données de listes et leurs tris. Voici une liste en Python :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "327780ed-4331-43ad-921b-9e42d762f2aa",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "L = [3, 2 , 4]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01263b26-3983-4073-aaff-1a30d69ff914",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Pour la trier vous pouvez utiliser ```.sort()``` [(doc)](https://docs.python.org/3/howto/sorting.html) qui modifie la liste actuelle :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "79f084ad-942d-46c6-bfe7-2722eeeda426",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "L = [3, 2 , 4]\n",
+    "L.sort()\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f04dbfe7-c000-4c2e-a2c4-e6187fe17ba7",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Soit vous créez une nouvelle liste triée qui ne modifie pas la liste actuelle en utilisant ```sorted``` [(doc)](https://docs.python.org/3/howto/sorting.html) :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c9b79862-a7b6-4b74-af5c-3d36f85f7b67",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "L = [3, 2 , 4]\n",
+    "print(sorted(L))\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4affcb3d-d8ae-4c5e-a7f5-fbc59b1fff76",
+   "metadata": {},
+   "source": [
+    "Enfin les fonctions de tri peuvent prendre un paramètre `key` afin d'indiquer sur quel attribut de la liste réaliser le tri. Ci dessous le tri sera fait sur le premier élément d'une liste de listes à trier :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "76f37b8b-69f5-4df0-91ae-b221a372e519",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "L = [[3, \"C\"], [1, \"A\"], [2, \"B\"]]\n",
+    "L.sort(key=lambda x: x[0])\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c815465f",
+   "metadata": {},
+   "source": [
+    "### Chargement d'un fichier en dictionnaire\n",
+    "\n",
+    "Le code ci-dessous permet de charger ce fichier dans la variable `students_list`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fe36de75-c9c4-49b7-ad79-de78c4f5b3ca",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "students_list = []\n",
+    "\n",
+    "with open(\"etudiants.txt\") as f:\n",
+    "    keys = None\n",
+    "    for line in f:\n",
+    "        l = [w.strip() for w in line.split(';')]\n",
+    "        if keys is None:\n",
+    "            keys = l\n",
+    "        else:\n",
+    "            students_list.append({k:v for k, v in zip(keys, l)})"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cfb09dcd-d8eb-474d-9f01-bff6de7b114a",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Un echantillon du jeu de données vous est donné comme suit, il s'agit une liste de dictionnaires [(doc)](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a0ab86a7-ed2a-4265-be05-fabd7a7b7fe5",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "students_list[0:2]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d54fe400",
+   "metadata": {},
+   "source": [
+    "**Question 1.1 -** Calculez la moyenne de tous les étudiants disponibles dans la liste d'étudiants `students_list`. Vous nommerez votre fonction `average_grade` et lui donnerez en paramètre la variable `L` qui contient la liste d'étudiant. Conseil : pensez à convertir les variables au bon type de données (par ex. en utilisant `int()`ou `float()`)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "084ca248-e638-4416-9fed-32dde916fb5b",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "91158fa1e745aa0e8763ed62e53c76f7",
+     "grade": false,
+     "grade_id": "cell-0aa9f72deedd3eb2",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def average_grade(L: list)-> int:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "66486e51-46fa-4475-a990-9764f1206f21",
+   "metadata": {},
+   "source": [
+    "La moyenne attendue de votre fonction est :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e6086d5b-1a84-4cee-8bd3-b3acf46d68d3",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "average_grade(students_list)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "65b4a7d1-d0d6-4ec4-a609-b7eb42157cea",
+   "metadata": {},
+   "source": [
+    "Le test ci-dessous doit donc être validé (autrement dit aucune `Exception` ne doit être lancée) :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "836938d8-a4c7-44e2-b17b-2159acd11aad",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert average_grade(students_list) == 16.6"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2f986196-2afa-4baf-96a3-3d22280e6c22",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "**Question 1.2 -** Trouver la note maximale de manière _récursive_ et comparez avec la fonction `max` (qui peut prendre un argument `key` afin de trier par note) donnée ci-dessous. Attention aux types des données."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "45624183-f5e7-43ae-9e41-ab8b456d9360",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "cd1544ebc215b597758489fe050ce11e",
+     "grade": false,
+     "grade_id": "cell-103fc5f998c99492",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def find_maximum_recursive(L: list)-> str:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "59684c44-83db-47c3-a192-781041fc3b59",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert find_maximum_recursive(students_list) == int(max(students_list, key=lambda x: int(x[\"note\"]))[\"note\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a9bca555-e31a-4294-bdac-d9e2ff5fa950",
+   "metadata": {},
+   "source": [
+    "**Question 1.3 -** Trouver deux étudiants qui ont la même note, et renvoyez leurs noms sous forme de `Tuple`. Conseil : \n",
+    "\n",
+    "- parcourez la liste et mémoriser les notes que vous parcourrez;\n",
+    "- si une note a déjà été parcourue alors renvoyer l'indice du dictionnaire;\n",
+    "- enfin renvoyez les noms des étudiants"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1dd770ee-1c63-4fcc-b564-158803c665e9",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "089205cb93f662ef5a024c55dc88359a",
+     "grade": false,
+     "grade_id": "cell-01928f10678cd675",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def find_same_grade(L: list)-> tuple:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "dbfbaf85-01b6-4bbc-ae1e-b9e7cc47489e",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "find_same_grade(students_list)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5ef24de8-ed61-40e1-ad9a-26f118223c17",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert find_same_grade(students_list) == ('Dupond', 'Dupont')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0f948f2e",
+   "metadata": {},
+   "source": [
+    "**Question 1.4 -** Trier la liste de données par ordre croissant en implémentant un _tri par sélection_ fourni dans le pseudo-code ci-dessous (issu de [cette page](https://fr.wikipedia.org/wiki/Tri_par_s%C3%A9lection)). L'argument `key` permet d'indiquer sur quel attribut réaliser le tri (ici ce sera la note). Voir l'usage de cet attribut dans la cellule de test suivante.\n",
+    "\n",
+    "```\n",
+    "   procédure tri_selection(tableau t)\n",
+    "       n ← longueur(t) \n",
+    "       pour i de 0 à n - 2\n",
+    "           min ← i       \n",
+    "           pour j de i + 1 à n - 1\n",
+    "               si t[j] < t[min], alors min ← j\n",
+    "           fin pour\n",
+    "           si min ≠ i, alors échanger t[i] et t[min]\n",
+    "       fin pour\n",
+    "   fin procédure\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "03e651d7-1143-4a9f-b453-3469d5b75e52",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "461842f0bd10a79d92c3adb61e9e70fe",
+     "grade": false,
+     "grade_id": "cell-3ee4eefc84f634bc",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def sort_selection(L: list, key=lambda x: x) -> list:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d95d2146-847a-4c21-9a9a-af277d236aea",
+   "metadata": {},
+   "source": [
+    "Comparer votre tri avec la méthode `sorted` de Python."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e27a7071-e10b-4801-8d16-aa611f0866f6",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "768c025dd7d7b842b6ac47a7a2b8e107",
+     "grade": false,
+     "grade_id": "cell-4deb9caaaa6d474f",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "dae866db",
+   "metadata": {},
+   "source": [
+    "## Exercice 2 : Piles et files\n",
+    "\n",
+    "Désormais nous allons implémenter de nouvelles structures de manipulation de listes : les Piles et les Files. Et à terme réaliser un tri de plus en plus efficace (avec un Tas). Nous allons commencer avec la Pile dont nous vous fournissons la structure de données, nommée `Stack` et disponible ci-desous:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c4f1b0a9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Stack:\n",
+    "    def __init__(self):\n",
+    "        self.items = []\n",
+    "\n",
+    "    def push(self, item):\n",
+    "        self.items.append(item)\n",
+    "\n",
+    "    def pop(self):\n",
+    "        if not self.is_empty():\n",
+    "            return self.items.pop()\n",
+    "\n",
+    "    def peek(self):\n",
+    "        if not self.is_empty():\n",
+    "            return self.items[-1]\n",
+    "\n",
+    "    def is_empty(self):\n",
+    "        return len(self.items) == 0"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5ee3c79e-be53-4d98-a2fb-3b0e9adadeb8",
+   "metadata": {},
+   "source": [
+    "La pile ci-dessus a son équivalent avec la méthode `LifoQueue` du module `queue` de pile défini ci-dessous [(doc)](https://docs.python.org/3/library/queue.html). Nous voyons bien que le dépilement renvoie les données dans l'ordre inverse de leur empillement."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "77dee078-c30f-40a0-bd29-f64c978b3e0b",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import queue\n",
+    "pile = queue.LifoQueue()\n",
+    "for i in range (5): \n",
+    "    pile.put(i)\n",
+    "while not pile.empty():\n",
+    "    print(pile.get(), end=\" \")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bfaae7f4",
+   "metadata": {},
+   "source": [
+    "**Question 2.1 -** Utiliser la pile `Stack` afin d'empiler les données de la liste `students_list`. Maintenant dépilez cette pile et comparer les résultats avec la méthode `LifoQueue` afin de vérifier que vous obtenez les mêmes résultats (avec le `while` fourni dans le code ci-dessous) :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3ad4b923-5f23-4921-b02e-f8b9fd22dd55",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "b710d25ada58e842e7bcd7333d141cc3",
+     "grade": false,
+     "grade_id": "cell-63bc7e329d9959d4",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "pile = queue.LifoQueue()\n",
+    "s = Stack()\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()\n",
+    "\n",
+    "while not s.is_empty() and not pile.empty():\n",
+    "    assert s.pop() == pile.get()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "78b1b0fb-41fb-4e2e-8c2b-3a040fbcc5e0",
+   "metadata": {},
+   "source": [
+    "**Question 2.2 -** Transformer la structure de Pile `Stack` en une File (que vous nommerez `Queue`) et vérifiez que vous obtenez les mêmes résultats en récupérant les données qu'avec le module `Queue()` de Python."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "7ac004cd-f59e-4aa8-a31d-961e24acba69",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "084870f7cbddd7dc85c2b1c02c8648d3",
+     "grade": false,
+     "grade_id": "cell-a9eea459cf78c621",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Queue():\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9b588c0e-d8b8-4a57-b54f-6aef316bb5c5",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "414f416a2a624101edaa0bdeb57fee51",
+     "grade": false,
+     "grade_id": "cell-a259250b447e39e2",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "file = queue.Queue()\n",
+    "f = Queue()\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()\n",
+    "\n",
+    "while not f.is_empty() and not file.empty():\n",
+    "    assert f.pop() == file.get()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5a8722ae-500d-4956-9b8c-18e664e5b09f",
+   "metadata": {},
+   "source": [
+    "Nous voyons bien que le défilement renvoie les données dans l'ordre de leur empillement afin de respecter le principe de File."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e1f0a957-2c18-4edd-b37b-d766ac1e8557",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "**Question 2.3** - Mettez à jour votre File afin de ne pas générer d'exception `IndexError`. On peut par exemple renvoyer une valeur de type `None` si aucune valeur n'est disponible."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "49a596f0-fc7c-4158-bab1-e715e1cf6a57",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "file = Queue()\n",
+    "try:\n",
+    "    assert file.pop() == None # si on renvoie None pour une file vide, pas d'Exception !\n",
+    "except IndexError:\n",
+    "    print(\"On ne doit pas générer d'exception IndexError !\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9ebbd490-abcd-45e4-8296-c311e34ddf2d",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "**Question 2.4** - Enfin, transformer la file (classe `Queue`) pour en faire une file de priorité `FilePriorite`. Pour rappel, une file de priorité renvoie les éléments selon un critère particulier (par exemple la note minimale des valeurs contenues dans la file). \n",
+    "\n",
+    "Conseil \n",
+    "\n",
+    "- garder la liste des valeurs internes constamment triée lors de l'ajout;\n",
+    "- pour cela inclure la nouvelle valeur avec la méthode `ajoute()` à la bonne place (en conservant l'ordre de la liste interne) avec `.insert(index, valeur)`\n",
+    "\n",
+    "Nous vous fournissons aussi le module `PriorityQueue` qui est une file de priorité existante [(doc)](https://docs.python.org/3/library/queue.html) afin de comparer votre code."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fa163d01-ed34-447e-8b55-6198140c349b",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "from queue import PriorityQueue \n",
+    "import random\n",
+    "    \n",
+    "filep = PriorityQueue()\n",
+    "list_random = [random.randint(1, 10) for _ in range(5)] # Liste aléatoire\n",
+    "\n",
+    "for i in list_random: filep.put(i)\n",
+    "\n",
+    "while not filep.empty(): \n",
+    "  print(filep.get(), end=\" \")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "738fe9f0-7885-40b6-a8cf-eb0c7cd8f3aa",
+   "metadata": {},
+   "source": [
+    "Remplir le code ci-dessous basé sur la file afin d'en faire une file de priorité. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3b0a1122-5d8f-4f5f-8ef4-460f9896f4b6",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "69949417a33fbf1bbe25be57237c60e8",
+     "grade": false,
+     "grade_id": "cell-f5186a99d30ca43e",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class FilePriorite():\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4e608d6b-458b-4836-8ab2-4371d96ae54b",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "a56011d08cd37ac3315bef7a813524ce",
+     "grade": false,
+     "grade_id": "cell-76cf4fdc1a271293",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "filep = PriorityQueue()\n",
+    "f = FilePriorite()\n",
+    "\n",
+    "note_list = [student[\"note\"] for student in students_list]\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()\n",
+    "\n",
+    "while not f.is_empty() and not filep.empty():\n",
+    "    assert f.pop() == filep.get()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "77038e6d-0b73-434c-910d-c7da733b643a",
+   "metadata": {},
+   "source": [
+    "## Exercice 3 : Arbre binaire complet sous forme de liste"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5f3fc128-2a2e-42bd-924a-d691c09150d6",
+   "metadata": {},
+   "source": [
+    "Nous allons maintenant implémenter **arbre binaire complet**. Cet arbre sera utile pour l'exercice suivant et la création d'un Tas. Cet arbre (dans sa configuration [min-heap](https://en.wikipedia.org/wiki/Min-max_heaphttps://en.wikipedia.org/wiki/Min-max_heap), où les données sont renvoyées par ordre croissant) satisfait la propriété suivante : la valeur de tout noeud est inférieure à celle de ses enfant. Cet arbre binaire sera de surcroît implémenté en utilisant un tableau (car il s'agit d'un arbre _complet_ où tous les niveaux sont remplis, sauf éventuellement le dernier). L'arbre binaire possède des noeuds ayant un index $i$, avec un fils gauche et un fils droit. Le tableau et l'arbre sont reliés de la façon suivante : \n",
+    "\n",
+    "- La racine a la position $i = 0$ (cette valeur sera renvoyée par la fonction `get_racine`)\n",
+    "- Le parent a la position $\\lfloor (i - 1)/ 2 \\rfloor$ (fonction `get_parent`)\n",
+    "- Le fils gauche a la position $2 \\times i + 1$ (fonction `get_fils_gauche`)\n",
+    "- Le fils droit a la position  $2 \\times i + 2$ (fonction `get_fils_droit`)\n",
+    "\n",
+    "```\n",
+    "        3\n",
+    "       / \\\n",
+    "      2   5\n",
+    "     / \\  /\n",
+    "    1  4 6 \n",
+    "          \n",
+    "\n",
+    "La liste correspondante :\n",
+    "[3, 2, 5, 1, 4, 6]\n",
+    "```\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ea502a0e-faa7-4bb2-9627-35cd128521a4",
+   "metadata": {},
+   "source": [
+    "**Exercice 3.1** - Implémentez un arbre binaire sous forme de classe appellée `BinaryTree` (basée sur la file de priorité) avec les fonctions ci-dessus (`get_racine`, `get_parent`, `get_fils_gauche`, `get_fils_droit`). Vous rajouterez une méthode `taille`qui renvoie la taille de l'arbre binaire (longueur de la liste interne)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d6648668-c0e3-47d5-bd83-a49785939877",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "c91ff069482e113d672ed13d2baa8f4b",
+     "grade": false,
+     "grade_id": "cell-528191aadbf86414",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class BinaryTree():\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d0dd4680-92db-4dad-8647-951269330870",
+   "metadata": {},
+   "source": [
+    "**Exercice 3.2** - Assurez vous que tous les tests ci-dessous sont validés."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ac65be98-9649-4753-8ead-c0deb89f5f0c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# test arbre vide\n",
+    "tree_empty = BinaryTree()\n",
+    "assert tree_empty.taille() == 0\n",
+    "assert tree_empty.get_racine() == None\n",
+    "assert tree_empty.get_fils_gauche()[0] == None  \n",
+    "assert tree_empty.get_fils_droit()[0] == None  "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "f548b21a-b2f5-4de5-9261-38d23035e25d",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "L = [3, 2, 5, 1, 4, 6]\n",
+    "tree_empty = BinaryTree(L)\n",
+    "assert tree_empty.taille() == len(L) # 6\n",
+    "assert tree_empty.get_racine() == L[0] # 3\n",
+    "assert tree_empty.get_fils_gauche()[0] == L[2*0+1] # 2\n",
+    "assert tree_empty.get_fils_droit()[0] == L[2*0+2] # 5"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "25213313-5058-415a-a3bc-7948c3d98588",
+   "metadata": {},
+   "source": [
+    "Cette structure de donnée sera utile pour la question suivante afin de créer un `Tas`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d9f0166d-d12f-42a1-989a-b7014117e73d",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercice 4 (Bonus) : Création d'un tas et tri par tas\n",
+    "\n",
+    "Une structure de donnée de `Tas` permet de réduire la complexité de manipulation d'une file de priorité. La particularité de cette méthode est de répartir le coût de la recherche du plus petit élément (qui sera renvoyé) entre l'ajout et la suppression. "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6061d866-51fb-48bc-9f1a-46b1b57a0ec0",
+   "metadata": {},
+   "source": [
+    "**Question 4.1 -** Implémentez une structure de `Tas`comme suit :\n",
+    "\n",
+    "- Créez une structure de données de `Tas` similaire au `BinaryTree`\n",
+    " \n",
+    "- Créez une méthode `inserer` (que l'on utilisera à la place d'`ajoute`) dont le principe est le suivant :\n",
+    "\n",
+    "    - Chaque nouveau noeud est rajouté comme dernier élément du tableau (à la fin donc)\n",
+    "\n",
+    "    - Comparez ce noeud à son parent et si il est plus grand que ce parent inversez-le\n",
+    "\n",
+    "    - Répétez tant que la condition ci-dessus est vraie et que la racine n'est pas atteinte\n",
+    "    \n",
+    "\n",
+    "- Créez une méthode `enlever` dont le principe est le suivant :\n",
+    "\n",
+    "    - Enlever l'élément racine de l'arbre (premier élément du tableau)\n",
+    "\n",
+    "    - Déplacer le dernier noeud de l'arbre (dernier élément du tableau) à la place de la racine de l'arbre\n",
+    "\n",
+    "    - Vérifier que la racine conserve la propriété de Tas (qu'elle est inférieur à ses enfants); si ce n'est pas le cas alors implémenter une méthode `descendre` définie par la suite.\n",
+    "\n",
+    "- Créez une méthode `descendre` qui : \n",
+    "\n",
+    "    - Prend le plus petit des enfants\n",
+    "    - Echange sa place avec lui si il est plus petit\n",
+    "    - Répéte cela tant qu'il existe des enfants\n",
+    "    \n",
+    "Attention : pensez à tester si il existe un fils droit et un fils gauche lors des opération de descente lors de l'insertion."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "301e69f3-4035-4b10-9c85-f4427d92e03b",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "1527573490f338be2ecd33a9df08ceb7",
+     "grade": false,
+     "grade_id": "cell-1f833c3f451e29d9",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Tas():\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0b467f58-c800-4ae3-b066-8717732a1095",
+   "metadata": {},
+   "source": [
+    "Votre tas doit valider les tests suivants :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3c41d4a7-5971-497b-b484-4a42a2480b06",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# test tas vide\n",
+    "tas_vide = Tas()\n",
+    "assert tas_vide.taille() == 0\n",
+    "assert tas_vide.get_racine() == None\n",
+    "assert tas_vide.get_fils_droit()[0] == None  \n",
+    "assert tas_vide.get_fils_droit()[0] == None  \n",
+    "\n",
+    "# test tas simple\n",
+    "tas_simple = Tas()\n",
+    "tas_simple.inserer(1)\n",
+    "tas_simple.inserer(2)\n",
+    "assert tas_simple.taille() == 2\n",
+    "\n",
+    "# test tas un peu plus complexe\n",
+    "tas = Tas()\n",
+    "liste = [1, 4, 10000, 2, 29, .2, 13, .5, 14, .1, 100]\n",
+    "liste_triee = sorted(liste)\n",
+    "for l in liste:\n",
+    "    tas.inserer(l)\n",
+    "\n",
+    "assert tas.taille() == len(liste)    \n",
+    "assert tas.get_racine() == liste_triee[0]\n",
+    "assert tas.get_fils_gauche(0) == (liste_triee[1], 1)\n",
+    "assert tas.get_fils_droit(0) == (liste_triee[2], 2)\n",
+    "\n",
+    "while not tas.est_vide():\n",
+    "    assert tas.enlever(0) == liste_triee.pop(0)\n",
+    "    assert tas.taille() == len(liste_triee)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ec678229-485e-4f3b-8c24-56febe7bd69e",
+   "metadata": {},
+   "source": [
+    "**Question 4.2 -** Implémentez un tri par tas en utilisant la structure de données de `Tas` que vous avez réalisé précédemment."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1d483588-4153-4614-b969-854846b08f4e",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "812a12d8443aeaac357684ff5a590f6f",
+     "grade": false,
+     "grade_id": "cell-3a78d4e48e46d4d9",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def triTas(l: list = []) -> list:\n",
+    "    t = Tas()\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e7ab0b07-f13c-4b95-b5fa-c38aea9b6ead",
+   "metadata": {},
+   "source": [
+    "Comparez à la méthode de tri `sorted`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4e9fd04a-910a-4d32-b0dc-0a1502599901",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "liste = [54,26,93,17,77,31,44,55,20]\n",
+    "l2 = triTas(liste.copy())\n",
+    "\n",
+    "assert(l2 == sorted(liste))\n",
+    "assert([] == triTas([]))\n",
+    "assert([1] == triTas([1]))\n",
+    "assert([1, 1] == triTas([1, 1]))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "49bae650-a23a-41f7-8896-8ac502cd71e8",
+   "metadata": {},
+   "source": [
+    "Pour information, le module `heapq` contient l'implémentation d'un tas en Python et s'utilise comme les Piles, Files, etc."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5bcc3ebf-749e-4a10-8b90-37cfd2488171",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import heapq\n",
+    "tas = []\n",
+    "\n",
+    "for i in range(5): heapq.heappush(tas, i)\n",
+    "\n",
+    "while not len(tas) == 0: \n",
+    "  print(heapq.heappop(tas), end=\" \")\n",
+    "\n",
+    "# 0 1 2 3 4"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7f774fa4-c586-4d5c-9cf3-5f9bb899f725",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "**Question 4.2 -** Comparez la performance (en temps) des méthodes de tri que vous avez implémenté dans les questions précentes."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "56e72b68-1d5c-4cea-8e9a-6d9f5f9ae34d",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "4c8bbe5f3d1599e3ca6db336ae4e3603",
+     "grade": false,
+     "grade_id": "cell-ca3b537d9dcc8790",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import time\n",
+    "import random\n",
+    "import matplotlib.pyplot as plt\n",
+    "\n",
+    "nvalues = [100, 500, 1500, 2000, 2500, 3000]\n",
+    "\n",
+    "timesSorted = []\n",
+    "timesSort = []\n",
+    "timesSelection = []\n",
+    "timesHeap = []\n",
+    "\n",
+    "for i in nvalues:\n",
+    "\n",
+    "    random.seed()\n",
+    "    p = 12**2\n",
+    "    liste = []\n",
+    "    \n",
+    "    for x in range(i): liste.append(random.randint(0, p))\n",
+    "\n",
+    "    # tri sorted\n",
+    "    c = liste.copy()\n",
+    "    a=time.perf_counter()\n",
+    "    triSorted = sorted(c)\n",
+    "    b=time.perf_counter()\n",
+    "    timesSorted.append(b-a)\n",
+    "\n",
+    "    # tri .sort()\n",
+    "    c = liste.copy()\n",
+    "    a=time.perf_counter()\n",
+    "    triSort = c\n",
+    "    triSort.sort()\n",
+    "    b=time.perf_counter()\n",
+    "    timesSort.append(b-a)\n",
+    "\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()\n",
+    "    \n",
+    "plt.plot(nvalues, timesSorted, \"g-\", label=\"Tri Sorted\")\n",
+    "plt.plot(nvalues, timesSort, \"b-\", label=\"Tri .sort()\")\n",
+    "plt.plot(nvalues, timesSelection, \"r-\", label=\"Tri Selection\")\n",
+    "plt.plot(nvalues, timesHeap, \"r-\", label=\"Tri Heap\")\n",
+    "plt.xlabel(\"Taille du jeu de données\")\n",
+    "plt.ylabel(\"Temps\")\n",
+    "plt.legend(loc=\"upper left\")\n",
+    "plt.title(\"Comparaison des performances des algorithmes de tri\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "04456b1e-92fd-4433-b230-8ea4374595a0",
+   "metadata": {},
+   "source": [
+    "Pour en savoir plus comment Python réalise le tri, lire la documentation du `TimSort` (doc)[https://en.wikipedia.org/wiki/Timsort] qui est l'algorithme de tri utilisé."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3e925273-2161-4c10-8e79-dabcc9bb38cb",
+   "metadata": {},
+   "source": [
+    "## Pour aller plus loin\n",
+    "\n",
+    "- Mettez à jour votre file afin de renvoyer [une exception](https://docs.python.org/3/tutorial/errors.html) si on demande une valeur qui n'est pas dans la structure de données (pile, file, etc.)\n",
+    "- Utilisez un [grand jeu de donnée](https://generatedata.com/) d'étudiants pour les premières questions."
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.10.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/TD02/code/Pile.py b/TD02/code/Pile.py
deleted file mode 100644
index 90754b41c0f74bb13f938d2785195e8b6b15f80c..0000000000000000000000000000000000000000
--- a/TD02/code/Pile.py
+++ /dev/null
@@ -1,20 +0,0 @@
-class Pile():
-    def __init__(self, values = []):
-        self.__values = []
-        for v in values:
-            self.ajoute(v)
-
-    def ajoute(self, v):
-        self.__values.append(v)
-        return v
-
-    def supprime(self):
-        v = self.__values.pop()
-        return v
-
-    def affiche(self):
-        for v in self.__values:
-            print(v)
-
-    def taille(self): 
-        return len(self.__values)
\ No newline at end of file
diff --git a/TD02/code/load.py b/TD02/code/load.py
deleted file mode 100644
index 0e10d85477875b2d7821f44428c44c7de5cdec36..0000000000000000000000000000000000000000
--- a/TD02/code/load.py
+++ /dev/null
@@ -1,12 +0,0 @@
-data = []
-
-with open("etudiants.txt") as f:
-    keys = None
-    for line in f:
-        l = [w.strip() for w in line.split(';')]
-        if keys is None:
-            keys = l
-        else:
-            data.append({k:v for k, v in zip(keys, l)})
-
-print(data)
\ No newline at end of file
diff --git a/TD02/code/selection.py b/TD02/code/selection.py
deleted file mode 100644
index 74fdbee7bb62f534392746f550706be491bb5ed0..0000000000000000000000000000000000000000
--- a/TD02/code/selection.py
+++ /dev/null
@@ -1,20 +0,0 @@
-def selectionSort(l: list = []) -> list:
-    """Tri par selection en ligne"""
-    for i in range(0, len(l)):
-        min = i
-        for j in range(i+1, len(l)):
-            if(l[j] < l[min]):
-                min = j
-        tmp = l[i]
-        l[i] = l[min]
-        l[min] = tmp
-    
-    return l  
-
-if __name__=="__main__": 
-    liste = [54,26,93,17,77,31,44,55,20]
-    
-    assert(sorted(liste) == selectionSort(liste.copy()))
-    assert([] == selectionSort([]))
-    assert([1] == selectionSort([1]))
-    assert([1, 1] == selectionSort([1, 1]))
\ No newline at end of file
diff --git a/TD02/code/test_analyse_simple.py b/TD02/code/test_analyse_simple.py
deleted file mode 100644
index 6c86d81ba5499f3ed4f4cf5915aae4b45f8938eb..0000000000000000000000000000000000000000
--- a/TD02/code/test_analyse_simple.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import time
-import random
-import matplotlib.pyplot as plt
-
-nvalues = [100, 500, 1500, 2000, 2500, 3000]
-
-timesSorted = []
-timesSort = []
-
-for i in nvalues:
-
-    random.seed()
-    p = 12**2
-    liste = []
-    
-    for x in range(i): liste.append(random.randint(0, p))
-
-    c = liste.copy()
-    a=time.perf_counter()
-    triSorted = sorted(c)
-    b=time.perf_counter()
-    timesSorted.append(b-a)
-
-    c = liste.copy()
-    a=time.perf_counter()
-    triSort = c
-    triSort.sort()
-    b=time.perf_counter()
-    timesSort.append(b-a)
-
-plt.plot(nvalues, timesSorted, "g-", label="Tri 1")
-plt.plot(nvalues, timesSort, "b-", label="Tri 2")
-plt.xlabel("Taille du jeu de données")
-plt.ylabel("Temps")
-plt.legend(loc="upper left")
-plt.title("Comparaison des performances des algorithmes de tri")
-plt.show()
\ No newline at end of file
diff --git a/TD02/code/test_heap.py b/TD02/code/test_heap.py
deleted file mode 100644
index 5514c098c8452628f127ff6ff3f9582da3dd258b..0000000000000000000000000000000000000000
--- a/TD02/code/test_heap.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import heapq
-tas = []
-
-for i in range(5): heapq.heappush(tas, i)
-
-while not len(tas) == 0: 
-  print(heapq.heappop(tas), end=" ")
-
-# 0 1 2 3 4
\ No newline at end of file
diff --git a/TD02/code/test_lifoqueue.py b/TD02/code/test_lifoqueue.py
deleted file mode 100644
index 09a4716f4c404fab7429b09349745dd1347e7557..0000000000000000000000000000000000000000
--- a/TD02/code/test_lifoqueue.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import queue
-pile = queue.LifoQueue()
-
-for i in range(5): pile.put(i)
-
-while not pile.empty(): 
-  print(pile.get(), end=" ")
-
-# 4 3 2 1 0
\ No newline at end of file
diff --git a/TD02/code/test_pile.py b/TD02/code/test_pile.py
deleted file mode 100644
index 96c377a3a6d62d2b14be0eff4d26b8693166cba1..0000000000000000000000000000000000000000
--- a/TD02/code/test_pile.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from pile import *
-
-p = Pile()
-
-for d in data:
-  p.ajoute(d) 
-  e = p.supprime()
-    
-print(e['nom'] + " " + e['prenom']) # Arthaud Nathalie
\ No newline at end of file
diff --git a/TD02/code/etudiants-large100.txt b/TD02/etudiants-large100.txt
similarity index 100%
rename from TD02/code/etudiants-large100.txt
rename to TD02/etudiants-large100.txt
diff --git a/TD02/code/etudiants.txt b/TD02/etudiants.txt
similarity index 100%
rename from TD02/code/etudiants.txt
rename to TD02/etudiants.txt
diff --git a/TD02/td2.pdf b/TD02/td2.pdf
deleted file mode 100755
index a62b663c83166f770b5fd7ade6758f0c8cbd76d4..0000000000000000000000000000000000000000
Binary files a/TD02/td2.pdf and /dev/null differ
diff --git a/TD03/INF-TC1-td03.ipynb b/TD03/INF-TC1-td03.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..4bd31c9af58a7eb3a85a03e0b253ab92141b0cd9
--- /dev/null
+++ b/TD03/INF-TC1-td03.ipynb
@@ -0,0 +1,754 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "a4c364d0",
+   "metadata": {},
+   "source": [
+    "NAME:"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e1098061-ab50-4ba8-aa59-0b76ec1049a2",
+   "metadata": {},
+   "source": [
+    "# INF TC1 - TD3 (2h) - Arbres binaires"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fc6c7558-96c4-435b-a841-e38c5d14bc9f",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b0997389-5a87-4e8d-9600-29ed76e01759",
+   "metadata": {},
+   "source": [
+    "### IMPORTANT A LIRE (SUR L'UTILISATION DE CE NOTEBOOK)\n",
+    "\n",
+    "Le but de votre travail est de répondre aux questions des exercices en **remplissant certaines cellules de ce notebook avec votre solution**. Ces cellules, une foit remplies et lancées au fur et à mesure de vos avancées, permettront de valider des tests écrits dans d'autres cellules de ce notebook. **Il est donc important de bien suivre les instructions et répondre aux questions dans l'ordre**, et ne pas changer le nom des fonctions et/ou les cellules. Pour résumer :\n",
+    "    \n",
+    "1) Répondez aux questions dans les cellules en dessous des questions.\n",
+    "\n",
+    "2) Votre code devra remplacer le texte suivant : \n",
+    "\n",
+    "```python\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()\n",
+    "```\n",
+    "\n",
+    "(vous pouvez effacer ces deux lignes quand vous les rencontrez mais ne modifiez pas les noms de fonctions sinon les tests ne marchent plus).\n",
+    "\n",
+    "3) Exécuter enfin les cellules dans l'ordre d'apparition, de haut en bas et si votre code est correct alors les tests (sous forme d'`assert` seront validés (ils ne lanceront pas d'exception du type `AssertionError` ). Vous pouvez lancer plusieurs fois la même cellule cela ne pose pas de soucis.\n",
+    "    \n",
+    "4) Vous pouvez créer de nouvelles cellules comme bon vous semble.\n",
+    "\n",
+    "**En cas de problème, une solution est de relancer les cellules depuis le début du notebook une par une.** Pensez à bien sauvegarder ce notebook et ne pas le remplacer par un notebook qui a le même nom.\n",
+    "\n",
+    "\n",
+    "## Chargement de fonctions\n",
+    "_Les fonctions ci-dessous seront nécessaire afin de mener à bien ce TD. Il faut donc les charger en exécutant leur cellulle. Ne pas les modifier._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "818565ab-9088-4729-94f9-601ca50de254",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import graphviz\n",
+    "from graphviz import Digraph\n",
+    "from IPython.display import display\n",
+    "def visualize_oop(root):\n",
+    "    def build(node, dot=None):\n",
+    "        if dot is None:\n",
+    "            dot = graphviz.Digraph(format='png')\n",
+    "\n",
+    "        if node is not None:\n",
+    "            dot.node(str(node.value))\n",
+    "\n",
+    "            if node.left is not None:\n",
+    "                dot.edge(str(node.value), str(node.left.value))\n",
+    "                build(node.left, dot)\n",
+    "\n",
+    "            if node.right is not None:\n",
+    "                dot.edge(str(node.value), str(node.right.value))\n",
+    "                build(node.right, dot)\n",
+    "\n",
+    "        return dot\n",
+    "\n",
+    "    return build(root)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "de645c99-52cf-4cff-9c6b-b156101ad47c",
+   "metadata": {},
+   "source": [
+    "## Objectif du TD\n",
+    "\n",
+    "Ce TD vous fera manipuler les arbres binaires, qui sont une structure de donnée efficace afin de trier des listes mais aussi de réaliser des opérations plus avancées grace à des méthodes de parcours en largeur et en profondeur."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "abde77ea-e21d-434e-b72e-a62ac464c793",
+   "metadata": {},
+   "source": [
+    "## Exercice 1 : Introduction aux arbres binaires\n",
+    "\n",
+    "Dans ce exercice nous allons créer et parcourir un arbre binaire. Un arbre binaire est un arbre qui a les propriétés suivantes : \n",
+    "\n",
+    "- il comporte des noeuds ayant au _maximum deux enfants_\n",
+    "- il est _complet_ si tous les noeuds de tous les niveaux ont deux enfants\n",
+    "- il est _équilibré_ si l'arbre est complet sauf pour le dernier niveau. \n",
+    "\n",
+    "Voici un exemple d'arbre binaire :\n",
+    "\n",
+    "```\n",
+    "      1\n",
+    "     / \\\n",
+    "    2   3\n",
+    "```\n",
+    "\n",
+    "Dans cet exercice nous stockeront l'arbre avec une structure de donnée _explicite_ en POO (comme ci-dessous) qui contient des valeurs entières (et uniques, à savoir deux noeuds n'auront pas la même valeur `value`) dans chaque noeud :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9318f291-f289-4eb6-a7f7-94cbc4e3f459",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value : int, left : Node = None, right : Node = None):\n",
+    "        self.value = value\n",
+    "        self.left = left\n",
+    "        self.right = right"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "31993aa6-7361-4a58-856d-32f3a3fcec36",
+   "metadata": {},
+   "source": [
+    "**Question 1.1** - Utilisez la structure de donnée `Node` ci-dessus afin d'implémenter l'arbre donné en introduction. Votre arbre sera stocké dans la variable `root`. Vous pouvez rajouter des noeuds supplémentaires à cet arbre (mais il doit rester binaire)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "48a9b647-260e-40a5-a3da-c11ed77a9e62",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "beb79688b5e5df1bdd12691ad714eac6",
+     "grade": false,
+     "grade_id": "cell-ffb20a795dbdbbdf",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "root = Node(1) # a modifier\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0a4461c4-09b8-4f9f-ad70-6b953dc4b7e6",
+   "metadata": {},
+   "source": [
+    "Les tests suivant doivent être validés (vous pouvez rajouter d'autres tests) :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c08d3050-ccba-4b51-8a01-1d2689455e96",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert root.value == 1\n",
+    "assert root.left.value == 2\n",
+    "assert root.right.value == 3"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2fc5d004-bed5-4e6f-adf9-649d8f1543fb",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Vous pouvez visualiser et comparer votre résultat avec la méthode `visualize_oop` comme ci-dessous:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1edd4902-6ce9-4ffa-90c9-2d5ce45052be",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "visualize_oop(root)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "24670502-ecd5-4d86-a32c-1d7d43eb04fe",
+   "metadata": {},
+   "source": [
+    "**Question 1.2.** Proposer une méthode `bfs` de _parcours en largeur_ de l'arbre afin d'afficher la valeur des noeuds dans l'ordre croissant. Pour cela vous utiliserez une structure de données de File (sous forme de liste, cela sera suffisant). Une méthode possible pour mener cela à bien consiste à :\n",
+    "\n",
+    "1. Intialiser la file avec la racine de l'arbre\n",
+    "2. Dé-filer une valeur et la stocker dans une liste de résultat\n",
+    "3. En-filer ses enfants (si il y en a) dans la file\n",
+    "4. Répéter l'étape 2 jusqu'à ce que la file soit vide, renvoyer le résultat"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1f92e83b-ba51-4fa4-a127-2aa970a96a26",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "0bc26f23814e161578948c843e79c770",
+     "grade": false,
+     "grade_id": "cell-b74454651b88cd22",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def bfs(node: Node):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c1b198c7-8387-4552-a163-7a70a70c61a3",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert bfs(root) == [1, 2, 3]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "675c8c46-ed69-4a2e-a9cf-57301112e3ab",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "**Question 1.3** - Écrire une fonction `depth` de calcul de la _profondeur_ d'un noeud d'un arbre. La profondeur est défini comme la distance entre ce noeud et la racine (celle-ci aura une profondeur de `0`). Cette fonction prendra la racine de l'arbre `root`en paramètre, ainsi que le noeud dont on veut calculer la profondeur avec le paramètre `target_value`.\n",
+    "\n",
+    "Conseil : s'inspirer de la fonction précédente en incluant la profondeur de chaque noeud parcouru lors de son ajout dans la file (autrement dit rajouter un tuple `(noeud, profondeur)` au lieu du noeud parcouru seulement."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6c21f3f7-0f21-47ad-a4ce-a2af7b9743d4",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "9f419294f2ed6434ef24d24f774cfb23",
+     "grade": false,
+     "grade_id": "cell-569264aa478d708a",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def depth(root: Node, target_value: int) -> int:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "37a27a50-68f4-486b-a0da-b0905b8db8dd",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert depth(root, 1) == 0\n",
+    "assert depth(root, 2) == 1\n",
+    "assert depth(root, 3) == 1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f8abb2f4-24dc-4346-9081-4400df30e3af",
+   "metadata": {},
+   "source": [
+    "**Question 1.4** - Écrire une fonction `height` de calcul de la _hauteur_ d'un arbre définie comme la prodondeur maximale possible dans un arbe. Vous pouvez l'implémenter comme la profondeur maximale des noeuds de l'arbre, ou bien de manière récursive."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4944b0bb-5f59-41c2-b5d9-052a0d5386dd",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "918bef40539310f48be01edac2ead58c",
+     "grade": false,
+     "grade_id": "cell-a85de0968c316f03",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def height(root: Node) -> int:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2d11935c-2212-4ec3-ba57-5303ec05b274",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert height(root) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "29fca7e0-aaf9-495b-822d-f20e1a672092",
+   "metadata": {},
+   "source": [
+    "**Question 1.5** - Valider si l'arbre est bien équilibré, autrement dit si il n'y a pas de différence de profondeur suppérieur à 1 entre les feuilles d'un arbre."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3b4f56e8-e4bf-4d27-97eb-b24995d741fe",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "25f3c6577ce17faa5ecaf7da2fd5ff00",
+     "grade": false,
+     "grade_id": "cell-a0382a54d10a6915",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def est_equlibre(root: Node) -> bool:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "69b03c9b-2092-4343-b9e4-7d9904a445b0",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert est_equlibre(root)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9e29fddc-c249-4b2a-a9d3-26e56f5474ab",
+   "metadata": {},
+   "source": [
+    "## Exercice 2 : Arbres syntaxiques\n",
+    "\n",
+    "Un arbre _syntaxique_ permet le stockage d'une expression structurée, par exemple une équation. Dans cet exercice nous allons modéliser un tel arbre sous forme d'arbre binaire (exemple ci-dessous à gauche) afin de réaliser un calcul arithmétique simple à partir de l'expression fournie de manière textuelle :\n",
+    "\n",
+    "Expression : `(3-2) * (7+(10/2)`\n",
+    "\n",
+    "Résultat : `12.0`\n",
+    "\n",
+    "Nous ferons l'hypothèse que les opérations sont limitées à `+ - / *`, seront toujours binaires et porteront sur des valeurs numériques entières (mais le résultat peut ne pas être un entier).\n",
+    "\n",
+    "```\n",
+    "        *\n",
+    "       / \\\n",
+    "      -   +\n",
+    "     / \\ / \\\n",
+    "    3  2  7  /\n",
+    "            / \\\n",
+    "           10  2\n",
+    "```\n",
+    "\n",
+    "Vous utiliserez la structure d'arbre binaire ci-dessous afin de le stocker :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e78ec913-cd5f-4304-8c8a-438758d909f4",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Noeud:\n",
+    "    def __init__(self, v = None, g = None, d = None) -> None:\n",
+    "        self.valeur = v\n",
+    "        self.gauche = g\n",
+    "        self.droit = d"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "88fbc62f-ae5a-4765-bf8f-bb127f5d5a13",
+   "metadata": {},
+   "source": [
+    "**Question 2.1** - Utilisez la structure de données d'arbre ci-dessus afin de stocker l'arbre syntaxique donné en exemple.\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4661ca46-489c-4330-9e72-64fe25e4b49c",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "9a963623ac7f40f0c6910f44793cd731",
+     "grade": false,
+     "grade_id": "cell-1d6f524873221e42",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "arbre = None # à changer\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cee8c8d3-f4ab-4dcc-931e-f0b8681b225c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert arbre.valeur == \"*\"\n",
+    "assert arbre.gauche.valeur == \"-\"\n",
+    "assert arbre.droit.valeur == \"+\""
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0be8aab9-1aba-4340-9235-eb3d1cc7fd29",
+   "metadata": {},
+   "source": [
+    "**Question 2.2** - Implémenter désormais une méthode d'évaluation (autrement dit de calcul) automatique d'un arbre syntaxique tel que vous l'avez stocké dans la variable `arbre` ci-dessus. \n",
+    "\n",
+    "Conseil : proposer une solution récursive avec un cas d'arrêt et des appels récursifs comme suit :\n",
+    "- Si la valeur du noeud en cours est un opérateur, l'appliquer sur les deux sous-branches\n",
+    "- Si c'est une valeur numérique, renvoyer cette valeur (cas d'arrêt car c'est une feuille de l'arbre)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "dc899d17-67fd-4cc9-bf92-f5f32e08f89e",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "8f62609d2ce85be293bb216a8d323109",
+     "grade": false,
+     "grade_id": "cell-0dd185dc430e92dd",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def eval(r: Noeud) -> float:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "00eb3e33-64b1-486f-97c8-d87de80f3a1a",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "eval(arbre)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "de5c394d-df35-4d7b-b057-164620b0b38d",
+   "metadata": {},
+   "source": [
+    "**Question 2.3** - Écrire une méthode permettant de construire l'arbre à partir d'une expression fournie sous forme de chaîne de caractère en entrée comme `( ( 3 - 2 ) * ( 7 + ( 10 / 2 ) ) )\"`. Les espaces sont nécessaires et vous permettront de faire un `.split(\" \")}`. \n",
+    "\n",
+    "Conseil : \n",
+    "- Parcourez caractère par caractère l'expression textuelle\n",
+    "- Et utilisez une Pile permettant la bonne construction de l'arbre au fur et à mesure de son parcours"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1c33faaa-2289-498f-9ef1-5afeb4da4628",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "fead415ff1f951ce23b7c095c48edb63",
+     "grade": false,
+     "grade_id": "cell-208b77e462e634c5",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def construit_arbre(exp: str) -> int:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "b56d0304-5d23-4e1c-91fb-09b511465ad5",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "r = construit_arbre(\"( ( 3 - 2 ) * ( 7 + ( 10 / 2 ) )\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "89a9015c-dd4e-409d-91b2-9b64b55288e9",
+   "metadata": {},
+   "source": [
+    "Enfin vérifiez que vous obtenez la bonne valeur en évaluant l'expression."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e5c49c1f-75e0-4872-8578-40a532c7cea1",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert eval(r) == 12.0"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "012a5378-a2b7-498f-8115-e35f55c529ce",
+   "metadata": {},
+   "source": [
+    "**Question 2.4 (Bonus) -** - Ecrire une fonction qui renvoie `True` ou `False` si l'arbre est bien un arbre syntaxique tel que défini en introduction. Autrement dit qu'il est binaire, et comporte des opérateurs partout sauf aux feuilles.\n",
+    "\n",
+    "Proposez une méthode itérative :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "823d29e7-66c3-41a0-bdad-da6862a5e420",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "a4ee40878d76de79bb5ed7fc79868fff",
+     "grade": false,
+     "grade_id": "cell-cebdce6182bc5905",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def valide_ite(r: Noeud) -> bool:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "06e73b57-959a-436f-bd7a-e12c615c805c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert valide_ite(arbre)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "dfdf1d42-60bb-4a7e-9cd4-e6cb72b8130a",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Proposez une méthode récursive :"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "df0033e9-c076-4cde-ab6f-982a3677ce05",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "21af62ada65e457d812b1d7342b00e09",
+     "grade": false,
+     "grade_id": "cell-6c1bba57e9405b22",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def valide_rec(r: Noeud) -> bool:\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9998c852-ec74-4225-9f01-4368899e303f",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert valide_rec(arbre)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "85c6a3e6-dea0-4e86-b7d9-b0c5735c3630",
+   "metadata": {},
+   "source": [
+    "## Pour aller plus loin\n",
+    "\n",
+    "- Rajouter des tests dans les exemples ci-dessus avec des arbres plus complexes\n",
+    "- Inclure des Exceptions dans votre code\n",
+    "- Créer une table de hachage afin de mémoriser les opérations déja réalisées pour l'arbre syntaxique"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9cbffdb0-7d54-4054-b13d-fd1dc1afd0f2",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.10.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/cours/08-binary-trees slides.pdf b/cours/08-binary-trees slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..c7a84d4ef3b605b95fef4100f9ec5b31b0f7e4b4
Binary files /dev/null and b/cours/08-binary-trees slides.pdf differ
diff --git a/cours/09-binary-trees-traversals slides.pdf b/cours/09-binary-trees-traversals slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..b5883eb9c00b7ac88c0313e133e637cac65e3165
Binary files /dev/null and b/cours/09-binary-trees-traversals slides.pdf differ
diff --git a/cours/10-trees slides.pdf b/cours/10-trees slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..0194606cefbfe4d7911629f3fce6a1ffb2b5c8b8
Binary files /dev/null and b/cours/10-trees slides.pdf differ