diff --git a/exercises/08-binary-trees-exercises.ipynb b/exercises/08-binary-trees-exercises.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7c840cd461e117625ee06cf01e70e72989de9a24
--- /dev/null
+++ b/exercises/08-binary-trees-exercises.ipynb
@@ -0,0 +1,425 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "91c9c0b9",
+   "metadata": {},
+   "source": [
+    "NAME:"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3bae696a-8e88-4a34-89f6-a0f4d9551e9b",
+   "metadata": {},
+   "source": [
+    "# Binary trees\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7c7461c1-fe15-405b-a2c9-709e6f9c3743",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a2428808-27d5-4d42-84b8-01632b1271dd",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercise 1: Write the code for this binary tree\n",
+    "\n",
+    "_Use a `dict()` data structure for the list of nodes._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "83b91119-09f7-4cba-a87b-19fc4a793e91",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from graphviz import Digraph\n",
+    "\n",
+    "dot = Digraph()\n",
+    "\n",
+    "dot.node_attr['shape'] = 'circle'\n",
+    "\n",
+    "dot.node('0', label='0')  # Root\n",
+    "dot.node('1')\n",
+    "dot.node('2')\n",
+    "dot.node('3')\n",
+    "dot.node('4')\n",
+    "dot.node('5')\n",
+    "\n",
+    "dot.edge('0', '1')\n",
+    "dot.edge('1', '4')\n",
+    "dot.edge('1', '5')\n",
+    "\n",
+    "dot.edge('0', '2', color='red')\n",
+    "dot.edge('2', '3', color='red')\n",
+    "\n",
+    "\n",
+    "dot # Render the graph"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1fca57f5-4b3c-4ad8-a4c0-9d1de647abf9",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "_Use a `Dict` data structure for nodes and also for edges edges._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fa1bce0f-7b06-4d20-8a1b-990bcd03bda9",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "e4c7bf49dab0dfd7b602a4c0c683b731",
+     "grade": false,
+     "grade_id": "cell-0f290aab7c180fb7",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cb16382b-e00d-498a-bab2-0b251f93d147",
+   "metadata": {},
+   "source": [
+    "_Use a `Tuple` data structure for nodes and edges._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a4cbc1d4-5adc-4cda-9c2a-24101bd1bed9",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "7738eb399dd344478be29fefebaf1ec2",
+     "grade": false,
+     "grade_id": "cell-ce11e1828bd74e71",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fb0e9336-603c-49c4-9617-9ccecdbf7156",
+   "metadata": {},
+   "source": [
+    "# Exercise: binary search tree\n",
+    "\n",
+    "_We assume we have a binary search tree (BST). Its main property is that for every node, the value of the left children is less than the value of the right children._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "02513514-0e1b-4c0d-a5fd-ac6b571231b7",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value):\n",
+    "        self.value = value\n",
+    "        self.left = None\n",
+    "        self.right = None\n",
+    "    def __str__(self):\n",
+    "        return str(self.value)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "055d2cea-4e45-402d-baf8-e50939c94132",
+   "metadata": {},
+   "source": [
+    "Write an `insert` function inserts a value in a tree so it preserves the BST property."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6492983d-054c-4488-b8ff-57b3878f5b7e",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "bd38bd2d4979e4e3054b3e37a4ca1ed1",
+     "grade": false,
+     "grade_id": "cell-b636f3646835e810",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def insert(root, value):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "7c2a2f74-a8b8-4cd6-a881-9181efdb7a64",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "a = Node(2)\n",
+    "insert(a, 3)\n",
+    "insert(a, 4)\n",
+    "insert(a, 1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "10b6d8de-fb38-41e3-92b9-957f04a6f1e4",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "visualize_oop(a)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "07ca3602-96fd-43d7-b7ac-54f92124a11d",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "# Exercice: calculate the height using OOP"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2e65ec3d-8e90-4e25-befb-d779713fa3f2",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value, l = None, r = None):\n",
+    "        self.value = value\n",
+    "        self.left = l\n",
+    "        self.right = r"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3bd05d7e-7e0c-4042-9aac-616960849de9",
+   "metadata": {},
+   "source": [
+    "In a recursive way:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c323b9af-98f6-45d6-9ee2-cffde39a2a16",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "42c8cd4604ffd18d8666aabe5247c397",
+     "grade": false,
+     "grade_id": "cell-b19dae2393fee8a2",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def recursive_tree_height(node):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9527fa59-87cf-4216-a7dc-ad0aa3330d4c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert recursive_tree_height(Node(2)) == 0\n",
+    "assert recursive_tree_height(Node(2, Node(3))) == 1\n",
+    "assert recursive_tree_height(Node(2, Node(3, Node(4)))) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7b46712d-472b-4997-90b4-acda29a17fb9",
+   "metadata": {},
+   "source": [
+    "In an interative way:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6cd2bdcf-d4ad-4103-88ed-ced3fb45f4e8",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "1afd752578f9f00f7fb8ab9b3a28226a",
+     "grade": false,
+     "grade_id": "cell-8cc9bfd56a6fcde6",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def iterative_tree_height(root):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "dac217fa-c9db-46ca-91a3-a834c3d0aa38",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert iterative_tree_height(Node(2)) == 0\n",
+    "assert iterative_tree_height(Node(2, Node(3))) == 1\n",
+    "assert iterative_tree_height(Node(2, Node(3, Node(4)))) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5e50ca4a-6aaf-4620-924a-eb6d8a00efaf",
+   "metadata": {},
+   "source": [
+    "# Utils"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "0c319da6-cee4-447f-b178-0ed04da67273",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "from graphviz import Digraph\n",
+    "from IPython.display import display\n",
+    "\n",
+    "class Node:\n",
+    "    def __init__(self, value, l = None, r = None):\n",
+    "        self.value = value\n",
+    "        self.left = l\n",
+    "        self.right = r\n",
+    "\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)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "b5866309-ceba-4d71-a2e0-5df6e5e18b25",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "visualize_oop(Node(3, Node(2)))"
+   ]
+  }
+ ],
+ "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/lectures/08-binary-trees slides.pdf b/lectures/08-binary-trees slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..5db8adba5cb9b9ca412ea71a3bbe3eb22c60100f
Binary files /dev/null and b/lectures/08-binary-trees slides.pdf differ
diff --git a/lectures/09-binary-trees-traversals slides.pdf b/lectures/09-binary-trees-traversals slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..1134dbd6ac9cfcd63963302af29abfe23aa2cee5
Binary files /dev/null and b/lectures/09-binary-trees-traversals slides.pdf differ
diff --git a/lectures/10-trees slides.pdf b/lectures/10-trees slides.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..6d5fd52a8662e16e0138809d372ef35a633f72f5
Binary files /dev/null and b/lectures/10-trees slides.pdf differ
diff --git a/notebooks/08-binary-trees.ipynb b/notebooks/08-binary-trees.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b3f1f95405c04d7d96669eeacd384e7c319a273f
--- /dev/null
+++ b/notebooks/08-binary-trees.ipynb
@@ -0,0 +1,1069 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "09fc003e",
+   "metadata": {},
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## Lecture 8: Binary trees\n",
+    "### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business\n",
+    "#### Romain Vuillemot\n",
+    "<center><img  src=\"figures/Logo_ECL.png\" style=\"width:300px\"></center>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "74743087",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f3ebe7d2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Outline\n",
+    "- Definitions\n",
+    "- Data structures\n",
+    "- Basic operations\n",
+    "- Properties"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a4973a08",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Definitions\n",
+    "\n",
+    ">  Tree is a hierarchical data structure with nodes connected by edges\n",
+    "\n",
+    "- A non-linear data structures (multiple ways to traverse it)\n",
+    "- Nodes are connected by only one path (a series of edges) so trees have no cycle\n",
+    "- Edges are also called links, they can be traversed in both ways (no orientation)\n",
+    "\n",
+    "We focus on _binary trees._\n",
+    "\n",
+    ">  Trees that have at most two children\n",
+    "\n",
+    "- Children can be ordered left child and the right child\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "28bb09dc",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Binary trees representation\n",
+    "\n",
+    "Trees are most commonly represented as a node-lin diagram, with the root at the top and the leaves (nodes without children) at the bottom)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 278,
+   "id": "51f0cf57",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "-"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"212pt\" height=\"188pt\"\n",
+       " viewBox=\"0.00 0.00 212.19 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-184 208.19,-184 208.19,4 -4,4\"/>\n",
+       "<!-- ROOT -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>ROOT</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"121.8\" cy=\"-162\" rx=\"34.39\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"121.8\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">ROOT</text>\n",
+       "</g>\n",
+       "<!-- Node 1 -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>Node 1</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"76.8\" cy=\"-90\" rx=\"36.29\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"76.8\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">Node 1</text>\n",
+       "</g>\n",
+       "<!-- ROOT&#45;&gt;Node 1 -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>ROOT&#45;&gt;Node 1</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M111.13,-144.41C105.86,-136.22 99.39,-126.14 93.48,-116.95\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"96.56,-115.26 88.2,-108.74 90.67,-119.05 96.56,-115.26\"/>\n",
+       "</g>\n",
+       "<!-- Node 2 -->\n",
+       "<g id=\"node5\" class=\"node\">\n",
+       "<title>Node 2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"167.8\" cy=\"-90\" rx=\"36.29\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"167.8\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">Node 2</text>\n",
+       "</g>\n",
+       "<!-- ROOT&#45;&gt;Node 2 -->\n",
+       "<g id=\"edge4\" class=\"edge\">\n",
+       "<title>ROOT&#45;&gt;Node 2</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M132.47,-144.76C137.85,-136.58 144.5,-126.45 150.58,-117.2\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"153.47,-119.18 156.04,-108.9 147.62,-115.33 153.47,-119.18\"/>\n",
+       "</g>\n",
+       "<!-- Leaf 1 -->\n",
+       "<g id=\"node3\" class=\"node\">\n",
+       "<title>Leaf 1</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"33.8\" cy=\"-18\" rx=\"33.6\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"33.8\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">Leaf 1</text>\n",
+       "</g>\n",
+       "<!-- Node 1&#45;&gt;Leaf 1 -->\n",
+       "<g id=\"edge2\" class=\"edge\">\n",
+       "<title>Node 1&#45;&gt;Leaf 1</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M66.61,-72.41C61.63,-64.3 55.51,-54.35 49.92,-45.25\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"52.92,-43.45 44.71,-36.76 46.96,-47.11 52.92,-43.45\"/>\n",
+       "</g>\n",
+       "<!-- Leaf 2 -->\n",
+       "<g id=\"node4\" class=\"node\">\n",
+       "<title>Leaf 2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"119.8\" cy=\"-18\" rx=\"33.6\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"119.8\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">Leaf 2</text>\n",
+       "</g>\n",
+       "<!-- Node 1&#45;&gt;Leaf 2 -->\n",
+       "<g id=\"edge3\" class=\"edge\">\n",
+       "<title>Node 1&#45;&gt;Leaf 2</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M86.99,-72.41C91.97,-64.3 98.08,-54.35 103.67,-45.25\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"106.64,-47.11 108.89,-36.76 100.67,-43.45 106.64,-47.11\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x104c33bb0>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "draw_binary_tree(binary_tree)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "55e54f01",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "##  Binary trees data structures\n",
+    "\n",
+    "Binary trees can be stored in multiple ways\n",
+    "\n",
+    "- The first element is the value of the node.\n",
+    "- The second element is the left subtree.\n",
+    "- The third element is the right subtree.\n",
+    "\n",
+    "Here are examples:\n",
+    "\n",
+    "- Adjacency list `T = {'A': ['B', 'C']}`\n",
+    "- Arrays `[\"A\", \"B\"]`\n",
+    "- Class / Object-oriented programming `Class Node()`\n",
+    "\n",
+    "Other are possible: using linked list, modules, etc.\n",
+    "\n",
+    "Adjacency lists are the most common ways and can be achieved in multiple fashions."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "30faa950",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "##  Binary trees data structures (dictionnaries and lists)\n",
+    "\n",
+    "_Binary trees using dictionnaries where nodes are keys and edges are Lists._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 199,
+   "id": "d495c8a5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "T = {\n",
+    "    'A' : ['B','C'],\n",
+    "    'B' : ['D', 'E'],\n",
+    "    'C' : [],\n",
+    "    'D' : [],\n",
+    "    'E' : []\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2b2c183",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Using OOP"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 200,
+   "id": "5df1c518",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value):\n",
+    "        self.value = value\n",
+    "        self.left = None\n",
+    "        self.right = None\n",
+    "        \n",
+    "    def get_value(self):\n",
+    "        return self.value\n",
+    "    \n",
+    "    def set_value(self, v = None):\n",
+    "        self.value = v"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 201,
+   "id": "abc855b1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "root = Node(4)\n",
+    "root.left = Node(2)\n",
+    "root.right = Node(5)\n",
+    "root.left.left = Node(1)\n",
+    "root.left.right = Node(3)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8b8ec2a0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Definitions on binary trees\n",
+    "\n",
+    "`Nodes` - a tree is composed of nodes that contain a `value` and `children`.\n",
+    "\n",
+    "`Edges` - are the connections between nodes; nodes may contain a value.\n",
+    "\n",
+    "`Root` - the topmost node in a tree; there can only be one root.\n",
+    "\n",
+    "`Parent and child` -  each node has a single parent and up to two children.\n",
+    "\n",
+    "`Leaf` - no node below that node.\n",
+    "\n",
+    "`Depth` - the number of edges on the path from the root to that node.\n",
+    "\n",
+    "`Height` - maximum depth in a tree."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b0bb3608",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "# Basic operations"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8726ff36",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Get the root of a tree\n",
+    "\n",
+    "_Return the topmost node in a tree (there can only be one root)._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 254,
+   "id": "1fbb1c2f",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def get_root(T):\n",
+    "    if (len(T.keys()) > 0):\n",
+    "        return list(T.keys())[0]\n",
+    "    else:\n",
+    "        return -1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 255,
+   "id": "6b4492dc",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'A'"
+      ]
+     },
+     "execution_count": 255,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_root(T)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 256,
+   "id": "ea01e802",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert get_root({}) == -1\n",
+    "assert get_root({\"A\": []}) == \"A\"\n",
+    "assert isinstance(get_root({\"A\": []}), str) # to make sure there is only 1 root (eg not a list)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3ffffeda",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Get the list of nodes\n",
+    "\n",
+    "_Return all the nodes in the tree (as a list of nodes names)._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 205,
+   "id": "3af082b7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def get_nodes(T):\n",
+    "    return list(T.keys())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 206,
+   "id": "ede5b5f4",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['A', 'B', 'C', 'D', 'E']"
+      ]
+     },
+     "execution_count": 206,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_nodes(T)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 208,
+   "id": "2d3305d5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert get_nodes(T) == ['A', 'B', 'C', 'D', 'E']\n",
+    "assert get_nodes({}) == []"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "db9c925d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Get the list of edges\n",
+    "\n",
+    "_Return all the edges as a list of pairs as `Tuple`._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 209,
+   "id": "b50fe9c2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def get_edges(graph):\n",
+    "    edges = []\n",
+    "    for node, neighbors in graph.items():\n",
+    "        for neighbor in neighbors:\n",
+    "            edges.append((node, neighbor))\n",
+    "    return edges"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 210,
+   "id": "8958bd83",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E')]"
+      ]
+     },
+     "execution_count": 210,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_edges(T)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 211,
+   "id": "30dd31d3",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert get_edges(T) == [('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E')]\n",
+    "assert get_edges({}) == []"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "95accba5",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Get the parent of a node\n",
+    "\n",
+    "_Return the parent node of a given node (and -1 if the root)._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 217,
+   "id": "37fbe31b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def get_parent(graph, node_to_find):\n",
+    "    for parent, neighbors in graph.items():\n",
+    "        if node_to_find in neighbors:\n",
+    "            return parent\n",
+    "    return None"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 218,
+   "id": "78e88d23",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert get_parent(T, 'D') == 'B'\n",
+    "assert get_parent(T, 'A') is None\n",
+    "assert get_parent({}, '') is None"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3fb6f347",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "### Check if the node is the root\n",
+    "\n",
+    "_Return True if the root not, else `None`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 226,
+   "id": "164e4ef7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def is_root(T, node):\n",
+    "    return find_parent(T, node) is None"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 227,
+   "id": "5c053617",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert is_root(T, 'A') == True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bba64730",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Get the children of a node\n",
+    "\n",
+    "_Given a node, return all its children as a `List`._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 228,
+   "id": "ac145c20",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def find_children(graph, parent_node):\n",
+    "    children = graph.get(parent_node, [])\n",
+    "    return children"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 229,
+   "id": "9444a66f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert find_children(T, 'A') == ['B', 'C']\n",
+    "assert find_children(T, 'B') == ['D', 'E']\n",
+    "assert find_children(T, 'C') == []"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6f600f3d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "### Check if the node is a leaf\n",
+    "\n",
+    "_Return `True` if the node has no children._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 233,
+   "id": "77f5f17c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def is_leaf(T, node):\n",
+    "    return len(find_children(T, node)) == 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 234,
+   "id": "5f5078d6",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert is_leaf(T, 'C') \n",
+    "assert not is_leaf(T, 'A')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a41e666e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Add/Delete a node\n",
+    "\n",
+    "_Given a tree as input._\n",
+    "\n",
+    "- Add a node to given a current partent\n",
+    "\n",
+    "- Remove a given node"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 267,
+   "id": "c9312a43",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def add_node(graph, parent, new_node):\n",
+    "    if parent in graph:\n",
+    "        graph[parent].append(new_node)\n",
+    "    else:\n",
+    "        graph[parent] = [new_node]\n",
+    "\n",
+    "def delete_node(graph, node_to_delete):\n",
+    "    for parent, children in graph.items():\n",
+    "        if node_to_delete in children:\n",
+    "            children.remove(node_to_delete)\n",
+    "            if not children:\n",
+    "                del graph[parent]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 268,
+   "id": "38181a0f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "U = {\"A\": []}\n",
+    "add_node(U, \"A\", 'F')\n",
+    "U"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4885c320",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Height of a tree\n",
+    "\n",
+    "_Calculate the longest path from the root to leaves. Tip: use a recursive approach_\n",
+    "\n",
+    "- if the node is a leaf, return 1\n",
+    "- for a current node, the height is the max height of its children + 1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 295,
+   "id": "ee2973b7",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'A': ['B', 'C'], 'B': ['D', 'E'], 'C': [], 'D': [], 'E': []}"
+      ]
+     },
+     "execution_count": 295,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "T"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "b7ef1fab",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "v"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 291,
+   "id": "6ef9af29",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def height(T, node):\n",
+    "    if node not in T:\n",
+    "        return 0  # leaf\n",
+    "    children = T[node]\n",
+    "    if not children:\n",
+    "        return 1  # leaf \n",
+    "    list_heights = []\n",
+    "    for child in children:\n",
+    "        list_heights.append(height(T, child))\n",
+    "    return 1 + max(list_heights)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 292,
+   "id": "44a54ec8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert height(T, 'A') == 3\n",
+    "assert height(T, 'B') == 2\n",
+    "assert height(T, 'C') == 1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e35608be",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Height of a binary tree\n",
+    "\n",
+    "\n",
+    "<img src=\"figures/hauteur-arbre.png\" style=\"width: 400px\">\n",
+    "\n",
+    "$n = 2^{(h+1)} - 1$\n",
+    "\n",
+    "$n + 1 = 2^{(h+1)}$\n",
+    "\n",
+    "$log(n + 1) = log(2^{(h+1)})$\n",
+    "\n",
+    "$log(n + 1) = (h+1) log(2)$\n",
+    "\n",
+    "$log(n + 1) / log(2) = h + 1$\n",
+    "\n",
+    "so $h = log(n + 1) / log(2) - 1$\n",
+    "\n",
+    "$h$ is equivalent to $log(n)$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "94f34cf8",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Binary trees (using Arrays)\n",
+    "\n",
+    "\n",
+    "<img src=\"figures/arbre-tableau.png\" style=\"width: 400px\">\n",
+    "\n",
+    "\n",
+    "In a complete or balanced binary tree: \n",
+    "- if the index of a node is equal to $i$, then the position indicating its left child is at $2i$, \n",
+    "- and the position indicating its right child is at $2i + 1$."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8afab007",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Visualize a tree"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 275,
+   "id": "610ad3bb",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"152pt\" height=\"188pt\"\n",
+       " viewBox=\"0.00 0.00 152.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-184 148,-184 148,4 -4,4\"/>\n",
+       "<!-- 0 -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>0</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-162\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">0</text>\n",
+       "</g>\n",
+       "<!-- 1 -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>1</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"72\" cy=\"-90\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"72\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">1</text>\n",
+       "</g>\n",
+       "<!-- 0&#45;&gt;1 -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>0&#45;&gt;1</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M92.74,-144.76C89.64,-136.72 85.81,-126.81 82.3,-117.69\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"85.64,-116.63 78.77,-108.56 79.11,-119.15 85.64,-116.63\"/>\n",
+       "</g>\n",
+       "<!-- 2 -->\n",
+       "<g id=\"node3\" class=\"node\">\n",
+       "<title>2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"126\" cy=\"-90\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"126\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
+       "</g>\n",
+       "<!-- 0&#45;&gt;2 -->\n",
+       "<g id=\"edge4\" class=\"edge\">\n",
+       "<title>0&#45;&gt;2</title>\n",
+       "<path fill=\"none\" stroke=\"red\" d=\"M105.26,-144.76C108.36,-136.72 112.19,-126.81 115.7,-117.69\"/>\n",
+       "<polygon fill=\"red\" stroke=\"red\" points=\"118.89,-119.15 119.23,-108.56 112.36,-116.63 118.89,-119.15\"/>\n",
+       "</g>\n",
+       "<!-- 4 -->\n",
+       "<g id=\"node5\" class=\"node\">\n",
+       "<title>4</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"18\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"18\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">4</text>\n",
+       "</g>\n",
+       "<!-- 1&#45;&gt;4 -->\n",
+       "<g id=\"edge2\" class=\"edge\">\n",
+       "<title>1&#45;&gt;4</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M61.33,-75.17C54.01,-65.68 44.12,-52.86 35.64,-41.86\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"38.45,-39.78 29.57,-34 32.91,-44.06 38.45,-39.78\"/>\n",
+       "</g>\n",
+       "<!-- 5 -->\n",
+       "<g id=\"node6\" class=\"node\">\n",
+       "<title>5</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"72\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"72\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">5</text>\n",
+       "</g>\n",
+       "<!-- 1&#45;&gt;5 -->\n",
+       "<g id=\"edge3\" class=\"edge\">\n",
+       "<title>1&#45;&gt;5</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M72,-71.7C72,-64.41 72,-55.73 72,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"75.5,-47.62 72,-37.62 68.5,-47.62 75.5,-47.62\"/>\n",
+       "</g>\n",
+       "<!-- 3 -->\n",
+       "<g id=\"node4\" class=\"node\">\n",
+       "<title>3</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"126\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"126\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n",
+       "</g>\n",
+       "<!-- 2&#45;&gt;3 -->\n",
+       "<g id=\"edge5\" class=\"edge\">\n",
+       "<title>2&#45;&gt;3</title>\n",
+       "<path fill=\"none\" stroke=\"red\" d=\"M126,-71.7C126,-64.41 126,-55.73 126,-47.54\"/>\n",
+       "<polygon fill=\"red\" stroke=\"red\" points=\"129.5,-47.62 126,-37.62 122.5,-47.62 129.5,-47.62\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x104c32b30>"
+      ]
+     },
+     "execution_count": 275,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from graphviz import Digraph\n",
+    "\n",
+    "dot = Digraph()\n",
+    "\n",
+    "dot.node_attr['shape'] = 'circle'\n",
+    "\n",
+    "dot.node('0', label='0')  # Root\n",
+    "dot.node('1')\n",
+    "dot.node('2')\n",
+    "dot.node('3')\n",
+    "dot.node('4')\n",
+    "dot.node('5')\n",
+    "\n",
+    "dot.edge('0', '1')\n",
+    "dot.edge('1', '4')\n",
+    "dot.edge('1', '5')\n",
+    "\n",
+    "dot.edge('0', '2', color='red')\n",
+    "dot.edge('2', '3', color='red')\n",
+    "\n",
+    "\n",
+    "dot # Render the graph"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01880f1d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Visualize a tree"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 277,
+   "id": "3a064bfb",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from graphviz import Digraph\n",
+    "from IPython.display import display\n",
+    "\n",
+    "def draw_binary_tree(tree_dict):\n",
+    "    # Create a new graph\n",
+    "    dot = Digraph(format='png')\n",
+    "    \n",
+    "    # Recursive function to add nodes and edges\n",
+    "    def add_nodes_and_edges(node, parent_name=None):\n",
+    "        if isinstance(node, dict):\n",
+    "            for key, value in node.items():\n",
+    "                # Add the node\n",
+    "                dot.node(key, key)\n",
+    "                # Add the edge to the parent (if it exists)\n",
+    "                if parent_name:\n",
+    "                    dot.edge(parent_name, key)\n",
+    "                # Recursively call the function for the children\n",
+    "                add_nodes_and_edges(value, key)\n",
+    "\n",
+    "    # Call the function to build the tree\n",
+    "    add_nodes_and_edges(tree_dict)\n",
+    "    \n",
+    "    # Display the graph in the notebook\n",
+    "    display(dot)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cb7726ee",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "celltoolbar": "Slideshow",
+  "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/notebooks/09-binary-trees-traversals.ipynb b/notebooks/09-binary-trees-traversals.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7ba83bef2fe0234932750be0fdf0d8c07c16c86c
--- /dev/null
+++ b/notebooks/09-binary-trees-traversals.ipynb
@@ -0,0 +1,592 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "a4973a08",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## Lecture 9: Binary trees traversals\n",
+    "### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business\n",
+    "#### Romain Vuillemot\n",
+    "<center><img  src=\"figures/Logo_ECL.png\" style=\"width:300px\"></center>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01f6da4e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6efad77c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Outline\n",
+    "\n",
+    "- Traversal methods\n",
+    "- Depth first\n",
+    "- Breadth first"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9fc3736a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Traversal methods\n",
+    "\n",
+    "> Methodes to explore and process all the nodes in a binary tree\n",
+    "\n",
+    "- Because Trees are non-linear, there are multiple possible paths"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7946fdbc",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Two main traversal strategies:\n",
+    "\n",
+    "<img src=\"figures/arbre-largeur-hauteur.png\" style=\"width: 400px\">\n",
+    "\n",
+    "1. **Depth-First Traversal (DFS):**\n",
+    "    - visiting a node (sarting with the root)\n",
+    "    - then recursively traversing as deep as possible \n",
+    "    - then explore another branch.\n",
+    "\n",
+    "2. **Breadth-First Traversal (BFS):**\n",
+    "    - visiting a node (sarting with the root)\n",
+    "    - explore all its neighbors (children) \n",
+    "    - then mode move to the children."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "66c57c10",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Depth-first\n",
+    "\n",
+    "**Pseudo-code for Depth-First Traversal:**\n",
+    "\n",
+    "1. Place the source node in the **stack**.\n",
+    "2. Remove the node from the top of the stack for processing.\n",
+    "3. Add all unexplored neighbors to the stack (at the top).\n",
+    "4. If the stack is not empty, go back to step 2.\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 60,
+   "id": "41790c1d",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "A\n",
+      "B\n",
+      "D\n",
+      "E\n",
+      "F\n",
+      "C\n"
+     ]
+    }
+   ],
+   "source": [
+    "def dfs(graph, start):\n",
+    "  stack = [start]\n",
+    "  while stack:\n",
+    "      vertex = stack.pop()\n",
+    "      print(vertex) # traitement\n",
+    "      stack.extend(graph[vertex])\n",
+    "\n",
+    "graph = {'A': set(['B', 'C']),\n",
+    "         'B': set(['D', 'E', 'F']),\n",
+    "         'C': set([]),\n",
+    "         'D': set([]),\n",
+    "         'E': set([]),\n",
+    "         'F': set([])\n",
+    "        }\n",
+    "\n",
+    "dfs(graph, 'A') # A B D F E C"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "da082c74",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Depth-first traversal: pre-order, in-order, and post-order.\n",
+    "\n",
+    "For **depth-first traversal**, there are different types of processing: *pre-order*, *in-order*, and *post-order*.\n",
+    "\n",
+    "- R = Root\n",
+    "- D = Right subtree\n",
+    "- G = Left subtree\n",
+    "\n",
+    "There are three (main) types of traversal, observing the position of R:\n",
+    "\n",
+    "- **Pre-order**: R G D\n",
+    "- **In-order**: G R D\n",
+    "- **Post-order**: G D R\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f0c20b5a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Depth-first traversal: pre-order, in-order, and post-order.\n",
+    "\n",
+    "For **depth-first traversal**, there are different types of processing: *pre-order*, *post-order*, and *in-order*.\n",
+    "\n",
+    "```python\n",
+    "def Preorder(R):\n",
+    "  if not empty(R):\n",
+    "    process(R)    # Root\n",
+    "    Preorder(left(R))   # Left\n",
+    "    Preorder(right(R))  # Right\n",
+    "\n",
+    "def Inorder(R):\n",
+    "  if not empty(R):\n",
+    "    Inorder(left(R))   # Left\n",
+    "    process(R)         # Root\n",
+    "    Inorder(right(R))  # Right\n",
+    "\n",
+    "def Postorder(R):\n",
+    "  if not empty(R):\n",
+    "    Postorder(left(R))  # Left\n",
+    "    Postorder(right(R)) # Right\n",
+    "    process(R)          # Rooot\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6d493663",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Depth-first traversal: pre-order\n",
+    "_Iterative implementation._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 62,
+   "id": "b0d812d9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def iterative_inorder_traversal(root):\n",
+    "    stack = []\n",
+    "    current = root\n",
+    "    while current is not None or stack:\n",
+    "        while current is not None:\n",
+    "            stack.append(current)\n",
+    "            current = current.left\n",
+    "        current = stack.pop()\n",
+    "        print(current.value)\n",
+    "        current = current.right"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f368960e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Depth-first traversal: pre-order\n",
+    "_Recursive implementation._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 114,
+   "id": "552dc46b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "TT = {\"dog\": [\"little\", \"very\"],\n",
+    "    \"little\": [\"the\"],\n",
+    "    \"the\": [],\n",
+    "      \"very\": [\"is\", \"cute\"],\n",
+    "      \"is\": [],\n",
+    "      \"cute\": []\n",
+    "    }"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 117,
+   "id": "2cafcf1c",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def preorder(T, node):\n",
+    "    if node is not None:\n",
+    "        if len(T[node]) > 0:\n",
+    "            preorder(T, T[node][0])\n",
+    "        print(node)\n",
+    "        if len(T[node]) > 1:\n",
+    "            preorder(T, T[node][1])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 118,
+   "id": "8b8f5c52",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "the\n",
+      "little\n",
+      "dog\n",
+      "is\n",
+      "very\n",
+      "cute\n"
+     ]
+    }
+   ],
+   "source": [
+    "preorder(TT, \"dog\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 68,
+   "id": "fbbb9408",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "the\n",
+      "little\n",
+      "dog\n",
+      "is\n",
+      "very\n",
+      "cute\n"
+     ]
+    }
+   ],
+   "source": [
+    "def preorder_traversal(node):\n",
+    "    if node is not None:\n",
+    "        if node.left:\n",
+    "            preorder_traversal(node.left)\n",
+    "        print(node.value)\n",
+    "        if node.right:\n",
+    "            preorder_traversal(node.right)\n",
+    "\n",
+    "root = Node(\"dog\")\n",
+    "root.left = Node(\"little\")\n",
+    "root.left.left = Node(\"the\")\n",
+    "root.right = Node(\"very\")\n",
+    "root.right.left = Node(\"is\")\n",
+    "root.right.right = Node(\"cute\")\n",
+    "preorder_traversal(root)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 69,
+   "id": "72f665f2",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"206pt\" height=\"188pt\"\n",
+       " viewBox=\"0.00 0.00 206.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-184 202,-184 202,4 -4,4\"/>\n",
+       "<!-- dog -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>dog</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"63\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"63\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">dog</text>\n",
+       "</g>\n",
+       "<!-- little -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>little</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">little</text>\n",
+       "</g>\n",
+       "<!-- dog&#45;&gt;little -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>dog&#45;&gt;little</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M54.65,-144.76C50.42,-136.55 45.19,-126.37 40.42,-117.09\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"43.68,-115.79 36,-108.49 37.46,-118.99 43.68,-115.79\"/>\n",
+       "</g>\n",
+       "<!-- very -->\n",
+       "<g id=\"node4\" class=\"node\">\n",
+       "<title>very</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">very</text>\n",
+       "</g>\n",
+       "<!-- dog&#45;&gt;very -->\n",
+       "<g id=\"edge3\" class=\"edge\">\n",
+       "<title>dog&#45;&gt;very</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M71.35,-144.76C75.58,-136.55 80.81,-126.37 85.58,-117.09\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"88.54,-118.99 90,-108.49 82.32,-115.79 88.54,-118.99\"/>\n",
+       "</g>\n",
+       "<!-- the -->\n",
+       "<g id=\"node3\" class=\"node\">\n",
+       "<title>the</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">the</text>\n",
+       "</g>\n",
+       "<!-- little&#45;&gt;the -->\n",
+       "<g id=\"edge2\" class=\"edge\">\n",
+       "<title>little&#45;&gt;the</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M27,-71.7C27,-64.41 27,-55.73 27,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"30.5,-47.62 27,-37.62 23.5,-47.62 30.5,-47.62\"/>\n",
+       "</g>\n",
+       "<!-- is -->\n",
+       "<g id=\"node5\" class=\"node\">\n",
+       "<title>is</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">is</text>\n",
+       "</g>\n",
+       "<!-- very&#45;&gt;is -->\n",
+       "<g id=\"edge4\" class=\"edge\">\n",
+       "<title>very&#45;&gt;is</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M99,-71.7C99,-64.41 99,-55.73 99,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-47.62 99,-37.62 95.5,-47.62 102.5,-47.62\"/>\n",
+       "</g>\n",
+       "<!-- cute -->\n",
+       "<g id=\"node6\" class=\"node\">\n",
+       "<title>cute</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"171\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">cute</text>\n",
+       "</g>\n",
+       "<!-- very&#45;&gt;cute -->\n",
+       "<g id=\"edge5\" class=\"edge\">\n",
+       "<title>very&#45;&gt;cute</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M113.92,-74.5C123.77,-64.92 136.86,-52.19 148.03,-41.34\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"150.29,-44.02 155.02,-34.54 145.41,-39 150.29,-44.02\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x1045bead0>"
+      ]
+     },
+     "execution_count": 69,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "visualize_oop(root)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c88e5f58",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Breadth-first traversal\n",
+    "\n",
+    "_Visit all the nodes in a tree or graph level by level._\n",
+    "\n",
+    "\n",
+    "```\n",
+    "      1\n",
+    "     / \\\n",
+    "    2   3\n",
+    "   / \\\n",
+    "  4   5\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 81,
+   "id": "73ceb6d8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def bfs_print(node):\n",
+    "    if node is None:\n",
+    "        return\n",
+    "\n",
+    "    queue = [node]\n",
+    "\n",
+    "    while queue:\n",
+    "        current_node = queue.pop(0)\n",
+    "        print(current_node.value, end=' ')\n",
+    "\n",
+    "        if current_node.left:\n",
+    "            queue.append(current_node.left)\n",
+    "\n",
+    "        if current_node.right:\n",
+    "            queue.append(current_node.right)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "id": "1e1a1f21",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "1 2 3 4 5 "
+     ]
+    }
+   ],
+   "source": [
+    "root = Node(1)\n",
+    "root.left = Node(2)\n",
+    "root.right = Node(3)\n",
+    "root.left.left = Node(4)\n",
+    "root.left.right = Node(5)\n",
+    "bfs_print(root)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7ba7af33",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Utils"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 83,
+   "id": "2dc5a89d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import graphviz\n",
+    "from graphviz import Digraph\n",
+    "from IPython.display import display"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 84,
+   "id": "7058a231",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "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)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "05b69326",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "celltoolbar": "Slideshow",
+  "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/solutions/08-binary-trees-exercises.ipynb b/solutions/08-binary-trees-exercises.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..133f662a42749bc099eb5add6c8b2a7a13353145
--- /dev/null
+++ b/solutions/08-binary-trees-exercises.ipynb
@@ -0,0 +1,657 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "3bae696a-8e88-4a34-89f6-a0f4d9551e9b",
+   "metadata": {},
+   "source": [
+    "# Binary trees\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7c7461c1-fe15-405b-a2c9-709e6f9c3743",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a2428808-27d5-4d42-84b8-01632b1271dd",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercise 1: Write the code for this binary tree\n",
+    "\n",
+    "_Use a `dict()` data structure for the list of nodes._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "83b91119-09f7-4cba-a87b-19fc4a793e91",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"152pt\" height=\"188pt\"\n",
+       " viewBox=\"0.00 0.00 152.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-184 148,-184 148,4 -4,4\"/>\n",
+       "<!-- 0 -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>0</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-162\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">0</text>\n",
+       "</g>\n",
+       "<!-- 1 -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>1</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"72\" cy=\"-90\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"72\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">1</text>\n",
+       "</g>\n",
+       "<!-- 0&#45;&gt;1 -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>0&#45;&gt;1</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M92.74,-144.76C89.64,-136.72 85.81,-126.81 82.3,-117.69\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"85.64,-116.63 78.77,-108.56 79.11,-119.15 85.64,-116.63\"/>\n",
+       "</g>\n",
+       "<!-- 2 -->\n",
+       "<g id=\"node3\" class=\"node\">\n",
+       "<title>2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"126\" cy=\"-90\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"126\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
+       "</g>\n",
+       "<!-- 0&#45;&gt;2 -->\n",
+       "<g id=\"edge4\" class=\"edge\">\n",
+       "<title>0&#45;&gt;2</title>\n",
+       "<path fill=\"none\" stroke=\"red\" d=\"M105.26,-144.76C108.36,-136.72 112.19,-126.81 115.7,-117.69\"/>\n",
+       "<polygon fill=\"red\" stroke=\"red\" points=\"118.89,-119.15 119.23,-108.56 112.36,-116.63 118.89,-119.15\"/>\n",
+       "</g>\n",
+       "<!-- 4 -->\n",
+       "<g id=\"node5\" class=\"node\">\n",
+       "<title>4</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"18\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"18\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">4</text>\n",
+       "</g>\n",
+       "<!-- 1&#45;&gt;4 -->\n",
+       "<g id=\"edge2\" class=\"edge\">\n",
+       "<title>1&#45;&gt;4</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M61.33,-75.17C54.01,-65.68 44.12,-52.86 35.64,-41.86\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"38.45,-39.78 29.57,-34 32.91,-44.06 38.45,-39.78\"/>\n",
+       "</g>\n",
+       "<!-- 5 -->\n",
+       "<g id=\"node6\" class=\"node\">\n",
+       "<title>5</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"72\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"72\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">5</text>\n",
+       "</g>\n",
+       "<!-- 1&#45;&gt;5 -->\n",
+       "<g id=\"edge3\" class=\"edge\">\n",
+       "<title>1&#45;&gt;5</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M72,-71.7C72,-64.41 72,-55.73 72,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"75.5,-47.62 72,-37.62 68.5,-47.62 75.5,-47.62\"/>\n",
+       "</g>\n",
+       "<!-- 3 -->\n",
+       "<g id=\"node4\" class=\"node\">\n",
+       "<title>3</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"126\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"126\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n",
+       "</g>\n",
+       "<!-- 2&#45;&gt;3 -->\n",
+       "<g id=\"edge5\" class=\"edge\">\n",
+       "<title>2&#45;&gt;3</title>\n",
+       "<path fill=\"none\" stroke=\"red\" d=\"M126,-71.7C126,-64.41 126,-55.73 126,-47.54\"/>\n",
+       "<polygon fill=\"red\" stroke=\"red\" points=\"129.5,-47.62 126,-37.62 122.5,-47.62 129.5,-47.62\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x107df21d0>"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from graphviz import Digraph\n",
+    "\n",
+    "dot = Digraph()\n",
+    "\n",
+    "dot.node_attr['shape'] = 'circle'\n",
+    "\n",
+    "dot.node('0', label='0')  # Root\n",
+    "dot.node('1')\n",
+    "dot.node('2')\n",
+    "dot.node('3')\n",
+    "dot.node('4')\n",
+    "dot.node('5')\n",
+    "\n",
+    "dot.edge('0', '1')\n",
+    "dot.edge('1', '4')\n",
+    "dot.edge('1', '5')\n",
+    "\n",
+    "dot.edge('0', '2', color='red')\n",
+    "dot.edge('2', '3', color='red')\n",
+    "\n",
+    "\n",
+    "dot # Render the graph"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1fca57f5-4b3c-4ad8-a4c0-9d1de647abf9",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "_Use a `Dict` data structure for nodes and also for edges edges._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 75,
+   "id": "fa1bce0f-7b06-4d20-8a1b-990bcd03bda9",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-0f290aab7c180fb7",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "T_dict = {\n",
+    "    ### BEGIN CODE\n",
+    "    '0': {\n",
+    "        '1': {\n",
+    "            '4': None,\n",
+    "            '5': None\n",
+    "        },\n",
+    "        '2': {\n",
+    "            '3': None\n",
+    "        },\n",
+    "    }\n",
+    "    ### END CODE\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cb16382b-e00d-498a-bab2-0b251f93d147",
+   "metadata": {},
+   "source": [
+    "_Use a `Tuple` data structure for nodes and edges._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 92,
+   "id": "a4cbc1d4-5adc-4cda-9c2a-24101bd1bed9",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-ce11e1828bd74e71",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "T_tuple = (\n",
+    "    ### BEGIN CODE\n",
+    "( ), ( )\n",
+    "    ### END CODE\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fb0e9336-603c-49c4-9617-9ccecdbf7156",
+   "metadata": {},
+   "source": [
+    "# Exercise: binary search tree\n",
+    "\n",
+    "_We assume we have a binary search tree (BST). Its main property is that for every node, the value of the left children is less than the value of the right children._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 72,
+   "id": "02513514-0e1b-4c0d-a5fd-ac6b571231b7",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value):\n",
+    "        self.value = value\n",
+    "        self.left = None\n",
+    "        self.right = None\n",
+    "    def __str__(self):\n",
+    "        return str(self.value)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "055d2cea-4e45-402d-baf8-e50939c94132",
+   "metadata": {},
+   "source": [
+    "Write an `insert` function inserts a value in a tree so it preserves the BST property."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 76,
+   "id": "6492983d-054c-4488-b8ff-57b3878f5b7e",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-b636f3646835e810",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def insert(root, value):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    if root is None:\n",
+    "        return Node(value)\n",
+    "    if value < root.value:\n",
+    "        root.left = insert(root.left, value)\n",
+    "    else:\n",
+    "        root.right = insert(root.right, value)\n",
+    "    return root\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 69,
+   "id": "7c2a2f74-a8b8-4cd6-a881-9181efdb7a64",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "<__main__.Node at 0x1069f31c0>"
+      ]
+     },
+     "execution_count": 69,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "a = Node(2)\n",
+    "insert(a, 3)\n",
+    "insert(a, 4)\n",
+    "insert(a, 1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 74,
+   "id": "10b6d8de-fb38-41e3-92b9-957f04a6f1e4",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"134pt\" height=\"188pt\"\n",
+       " viewBox=\"0.00 0.00 134.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-184 130,-184 130,4 -4,4\"/>\n",
+       "<!-- 2 -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"63\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"63\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
+       "</g>\n",
+       "<!-- 1 -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>1</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">1</text>\n",
+       "</g>\n",
+       "<!-- 2&#45;&gt;1 -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>2&#45;&gt;1</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M54.65,-144.76C50.42,-136.55 45.19,-126.37 40.42,-117.09\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"43.68,-115.79 36,-108.49 37.46,-118.99 43.68,-115.79\"/>\n",
+       "</g>\n",
+       "<!-- 3 -->\n",
+       "<g id=\"node3\" class=\"node\">\n",
+       "<title>3</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n",
+       "</g>\n",
+       "<!-- 2&#45;&gt;3 -->\n",
+       "<g id=\"edge2\" class=\"edge\">\n",
+       "<title>2&#45;&gt;3</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M71.35,-144.76C75.58,-136.55 80.81,-126.37 85.58,-117.09\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"88.54,-118.99 90,-108.49 82.32,-115.79 88.54,-118.99\"/>\n",
+       "</g>\n",
+       "<!-- 4 -->\n",
+       "<g id=\"node4\" class=\"node\">\n",
+       "<title>4</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"99\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">4</text>\n",
+       "</g>\n",
+       "<!-- 3&#45;&gt;4 -->\n",
+       "<g id=\"edge3\" class=\"edge\">\n",
+       "<title>3&#45;&gt;4</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M99,-71.7C99,-64.41 99,-55.73 99,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-47.62 99,-37.62 95.5,-47.62 102.5,-47.62\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x106c3a2f0>"
+      ]
+     },
+     "execution_count": 74,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "visualize_oop(a)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "07ca3602-96fd-43d7-b7ac-54f92124a11d",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "# Exercice: calculate the height using OOP"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "id": "2e65ec3d-8e90-4e25-befb-d779713fa3f2",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Node:\n",
+    "    def __init__(self, value, l = None, r = None):\n",
+    "        self.value = value\n",
+    "        self.left = l\n",
+    "        self.right = r"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3bd05d7e-7e0c-4042-9aac-616960849de9",
+   "metadata": {},
+   "source": [
+    "In a recursive way:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 83,
+   "id": "c323b9af-98f6-45d6-9ee2-cffde39a2a16",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-b19dae2393fee8a2",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def recursive_tree_height(node):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    if node is None:\n",
+    "        return -1\n",
+    "    left_height = recursive_tree_height(node.left)\n",
+    "    right_height = recursive_tree_height(node.right)\n",
+    "    return max(left_height, right_height) + 1\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 89,
+   "id": "9527fa59-87cf-4216-a7dc-ad0aa3330d4c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert recursive_tree_height(Node(2)) == 0\n",
+    "assert recursive_tree_height(Node(2, Node(3))) == 1\n",
+    "assert recursive_tree_height(Node(2, Node(3, Node(4)))) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7b46712d-472b-4997-90b4-acda29a17fb9",
+   "metadata": {},
+   "source": [
+    "In an interative way:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 84,
+   "id": "6cd2bdcf-d4ad-4103-88ed-ced3fb45f4e8",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-8cc9bfd56a6fcde6",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def iterative_tree_height(root):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    if root is None:\n",
+    "        return -1\n",
+    "\n",
+    "    level = 0\n",
+    "    current_level = [root]\n",
+    "\n",
+    "    while current_level:\n",
+    "        next_level = []\n",
+    "        for node in current_level:\n",
+    "            if node.left:\n",
+    "                next_level.append(node.left)\n",
+    "            if node.right:\n",
+    "                next_level.append(node.right)\n",
+    "        current_level = next_level\n",
+    "        level += 1\n",
+    "\n",
+    "    return level - 1\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 90,
+   "id": "dac217fa-c9db-46ca-91a3-a834c3d0aa38",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert iterative_tree_height(Node(2)) == 0\n",
+    "assert iterative_tree_height(Node(2, Node(3))) == 1\n",
+    "assert iterative_tree_height(Node(2, Node(3, Node(4)))) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5e50ca4a-6aaf-4620-924a-eb6d8a00efaf",
+   "metadata": {},
+   "source": [
+    "# Utils"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 46,
+   "id": "0c319da6-cee4-447f-b178-0ed04da67273",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "from graphviz import Digraph\n",
+    "from IPython.display import display\n",
+    "\n",
+    "class Node:\n",
+    "    def __init__(self, value, l = None, r = None):\n",
+    "        self.value = value\n",
+    "        self.left = l\n",
+    "        self.right = r\n",
+    "\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)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 47,
+   "id": "b5866309-ceba-4d71-a2e0-5df6e5e18b25",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
+       " -->\n",
+       "<!-- Pages: 1 -->\n",
+       "<svg width=\"62pt\" height=\"116pt\"\n",
+       " viewBox=\"0.00 0.00 62.00 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-112 58,-112 58,4 -4,4\"/>\n",
+       "<!-- 3 -->\n",
+       "<g id=\"node1\" class=\"node\">\n",
+       "<title>3</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n",
+       "</g>\n",
+       "<!-- 2 -->\n",
+       "<g id=\"node2\" class=\"node\">\n",
+       "<title>2</title>\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
+       "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
+       "</g>\n",
+       "<!-- 3&#45;&gt;2 -->\n",
+       "<g id=\"edge1\" class=\"edge\">\n",
+       "<title>3&#45;&gt;2</title>\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M27,-71.7C27,-64.41 27,-55.73 27,-47.54\"/>\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"30.5,-47.62 27,-37.62 23.5,-47.62 30.5,-47.62\"/>\n",
+       "</g>\n",
+       "</g>\n",
+       "</svg>\n"
+      ],
+      "text/plain": [
+       "<graphviz.graphs.Digraph at 0x106e17130>"
+      ]
+     },
+     "execution_count": 47,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "visualize_oop(Node(3, Node(2)))"
+   ]
+  }
+ ],
+ "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
+}