{
  "chapter": {
    "id": "arbres-binaires",
    "level": "terminale",
    "theme": "Structures de données",
    "title": "Arbres binaires",
    "description": "Définition d'un arbre binaire (nœuds, racine, feuilles,\nsous-arbres), terminologie (hauteur, profondeur, taille),\nparcours en profondeur (préfixe, infixe, postfixe) et en\nlargeur, propriétés des arbres équilibrés et complets,\napplications.",
    "parties": [
      {
        "id": "vocabulaire",
        "title": "Vocabulaire et propriétés"
      },
      {
        "id": "parcours",
        "title": "Parcours"
      },
      {
        "id": "implementation",
        "title": "Implémentation récursive"
      },
      {
        "id": "mesures",
        "title": "Taille, hauteur et complexité"
      }
    ],
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "definition"
      ],
      "title": "Définition d'un arbre binaire",
      "partie": "vocabulaire",
      "statement": "Qu'est-ce qu'un **arbre binaire** ?",
      "options": [
        {
          "text": "Un arbre dont chaque nœud contient exactement deux valeurs numériques distinctes",
          "correct": false,
          "feedback": "Erreur : « binaire » fait référence au nombre\nd'enfants, pas au nombre de valeurs par nœud.\n"
        },
        {
          "text": "Une structure linéaire avec deux pointeurs par élément",
          "correct": false,
          "feedback": "Erreur : c'est plutôt une liste doublement\nchaînée. Un arbre n'est pas linéaire mais\nhiérarchique.\n"
        },
        {
          "text": "Un arbre généalogique classique des liens de parenté",
          "correct": false,
          "feedback": "Erreur : un arbre généalogique n'est pas\nforcément binaire (chaque personne a au plus\ndeux parents directs, mais peut avoir plus de\ndeux enfants).\n"
        },
        {
          "text": "Une structure hiérarchique où chaque nœud a au plus deux enfants",
          "correct": true,
          "feedback": "Bonne réponse : un arbre binaire est un cas\nparticulier d'arbre où chaque nœud a $0$, $1$ ou\n$2$ enfants. La structure est récursive : chaque\nenfant est lui-même la racine d'un arbre binaire.\n"
        }
      ],
      "explanation": "Vocabulaire : **racine** (sommet), **nœud interne**\n(au moins un enfant), **feuille** (aucun enfant),\n**sous-arbre** (arbre formé par un nœud et ses\ndescendants). Cette définition est fondamentale."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "vocabulaire",
        "racine"
      ],
      "title": "Racine",
      "partie": "vocabulaire",
      "statement": "Combien de **racines** un arbre binaire possède-t-il ?",
      "options": [
        {
          "text": "Aucune",
          "correct": false,
          "feedback": "Erreur : un arbre non vide a toujours exactement\nune racine. Seul l'arbre vide n'a pas de racine.\n"
        },
        {
          "text": "Exactement une",
          "correct": true,
          "feedback": "Bonne réponse : la racine est le sommet de\nl'arbre, le nœud sans parent. Tout autre nœud\ndescend de la racine via une chaîne unique.\n"
        },
        {
          "text": "Cela dépend de la profondeur",
          "correct": false,
          "feedback": "Erreur : non, peu importe la profondeur, il y a\ntoujours une seule racine.\n"
        },
        {
          "text": "Plusieurs, autant que de feuilles",
          "correct": false,
          "feedback": "Erreur : confusion entre racine et feuille. Un\narbre a une racine et plusieurs feuilles\n(typiquement).\n"
        }
      ],
      "explanation": "L'unicité de la racine définit l'arbre. Si on a\nplusieurs « racines », on parle plutôt d'une\n**forêt** (ensemble disjoint d'arbres)."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "vocabulaire",
        "feuille"
      ],
      "title": "Feuille",
      "partie": "vocabulaire",
      "statement": "Qu'est-ce qu'une **feuille** dans un arbre binaire ?",
      "options": [
        {
          "text": "La racine de l'arbre",
          "correct": false,
          "feedback": "Erreur : la racine est au sommet, les feuilles\nsont les nœuds **terminaux**.\n"
        },
        {
          "text": "Un nœud à mi-hauteur de l'arbre",
          "correct": false,
          "feedback": "Erreur : aucune définition de feuille basée sur\nla hauteur.\n"
        },
        {
          "text": "Un nœud qui a exactement deux enfants",
          "correct": false,
          "feedback": "Erreur : ça, c'est un nœud **interne complet**.\nUne feuille n'a aucun enfant.\n"
        },
        {
          "text": "Un nœud qui n'a aucun enfant",
          "correct": true,
          "feedback": "Bonne réponse : une feuille est un nœud sans\ndescendant. Elle marque la fin d'une branche.\n"
        }
      ],
      "explanation": "Les feuilles sont importantes car elles marquent les\ncas de base des algorithmes récursifs sur les arbres.\nUn parcours s'arrête typiquement à chaque feuille."
    },
    {
      "id": "q04",
      "difficulty": 1,
      "skills": [
        "hauteur"
      ],
      "title": "Hauteur d'un arbre",
      "partie": "mesures",
      "statement": "Qu'appelle-t-on **hauteur** d'un arbre binaire ?",
      "options": [
        {
          "text": "La distance maximale séparant deux feuilles quelconques de l'arbre",
          "correct": false,
          "feedback": "Erreur : c'est le diamètre, pas la hauteur.\n"
        },
        {
          "text": "Le nombre de feuilles présentes dans tout l'arbre",
          "correct": false,
          "feedback": "Le nombre de feuilles\nrenseigne sur la\ncapacité finale d'un\narbre, mais ne mesure\npas sa hauteur.\n"
        },
        {
          "text": "Le plus long chemin de la racine à une feuille",
          "correct": true,
          "feedback": "Bonne réponse : convention courante, en\ncomptant le chemin en nombre d'**arêtes**. Un\narbre réduit à une racine a une hauteur de\n$0$. Un arbre vide a souvent la convention de\nhauteur $-1$.\n"
        },
        {
          "text": "Le nombre total de nœuds que contient l'arbre",
          "correct": false,
          "feedback": "Erreur : c'est la **taille**, pas la hauteur.\n"
        }
      ],
      "explanation": "Variante : certaines conventions comptent en\n**nombre de nœuds** plutôt que d'arêtes (la racine\nseule a alors une hauteur de $1$). Préciser la\nconvention dans tout exercice."
    },
    {
      "id": "q05",
      "difficulty": 1,
      "skills": [
        "profondeur"
      ],
      "title": "Profondeur d'un nœud",
      "partie": "vocabulaire",
      "statement": "La **profondeur** d'un nœud dans un arbre est :",
      "options": [
        {
          "text": "Le nombre de feuilles situées sous ce nœud",
          "correct": false,
          "feedback": "Erreur : c'est encore une autre quantité.\n"
        },
        {
          "text": "La longueur du chemin de la racine jusqu'à ce nœud",
          "correct": true,
          "feedback": "Bonne réponse : la racine a une profondeur de\n$0$, ses enfants $1$, etc. La profondeur est une\npropriété du nœud, alors que la hauteur est une\npropriété de l'arbre.\n"
        },
        {
          "text": "Le nombre total de descendants de ce nœud",
          "correct": false,
          "feedback": "Erreur : c'est plutôt la **taille du sous-arbre**\nenraciné en ce nœud.\n"
        },
        {
          "text": "La distance de ce nœud jusqu'à sa feuille la plus proche",
          "correct": false,
          "feedback": "Erreur : pas la définition standard de\nprofondeur.\n"
        }
      ],
      "explanation": "La hauteur de l'arbre est égale à la profondeur\nmaximale (parmi tous les nœuds). Les deux notions\nsont liées mais distinctes."
    },
    {
      "id": "q06",
      "difficulty": 1,
      "skills": [
        "parcours",
        "prefixe"
      ],
      "title": "Parcours préfixe",
      "partie": "parcours",
      "statement": "Dans un parcours **préfixe** (ou *pre-order*), dans\nquel ordre visite-t-on les nœuds ?",
      "options": [
        {
          "text": "Nœud, sous-arbre gauche, sous-arbre droit",
          "correct": true,
          "feedback": "Bonne réponse : « préfixe » car on visite le nœud\n**avant** ses enfants (préfixe = devant).\nUtilisation typique : copier un arbre.\n"
        },
        {
          "text": "Sous-arbre droit, nœud, sous-arbre gauche",
          "correct": false,
          "feedback": "Erreur : ordre inhabituel, ce n'est aucun des\nparcours classiques.\n"
        },
        {
          "text": "Sous-arbre gauche, nœud, sous-arbre droit",
          "correct": false,
          "feedback": "Erreur : c'est le parcours **infixe** (in-order).\n"
        },
        {
          "text": "Sous-arbre gauche, sous-arbre droit, nœud",
          "correct": false,
          "feedback": "Erreur : c'est le parcours **postfixe**\n(post-order).\n"
        }
      ],
      "explanation": "Mnémotechnique : **pré**fixe = nœud d'**abord** ;\n**in**fixe = nœud **au milieu** ; **post**fixe = nœud **après**. Le « préfixe », « infixe », « postfixe »\nréfère à la position du nœud dans la séquence des\nvisites."
    },
    {
      "id": "q07",
      "difficulty": 1,
      "skills": [
        "parcours",
        "infixe"
      ],
      "title": "Parcours infixe",
      "partie": "parcours",
      "statement": "Dans quel ordre s'effectue un parcours **infixe** d'un\narbre binaire ?",
      "options": [
        {
          "text": "Nœud, sous-arbre gauche, sous-arbre droit",
          "correct": false,
          "feedback": "Erreur : c'est le parcours **préfixe**.\n"
        },
        {
          "text": "Sous-arbre gauche, sous-arbre droit, nœud",
          "correct": false,
          "feedback": "Erreur : c'est le parcours **postfixe**.\n"
        },
        {
          "text": "Sous-arbre gauche, nœud, sous-arbre droit",
          "correct": true,
          "feedback": "Bonne réponse : on visite d'abord tout le\nsous-arbre gauche, puis le nœud lui-même, puis le\nsous-arbre droit. Ce parcours est très utile sur\nun arbre binaire de recherche : il donne les\nvaleurs **dans l'ordre croissant**.\n"
        },
        {
          "text": "Toutes les feuilles d'abord, puis tous les nœuds internes",
          "correct": false,
          "feedback": "Erreur : aucun parcours classique ne sépare\nainsi.\n"
        }
      ],
      "explanation": "Sur un arbre binaire de recherche, le parcours\ninfixe parcourt les valeurs dans l'ordre. C'est la\nraison principale d'utiliser cette structure pour\nmaintenir un ensemble trié dynamiquement."
    },
    {
      "id": "q08",
      "difficulty": 1,
      "skills": [
        "parcours",
        "postfixe"
      ],
      "title": "Parcours postfixe",
      "partie": "parcours",
      "statement": "Le parcours **postfixe** visite :",
      "options": [
        {
          "text": "Le sous-arbre gauche, puis le sous-arbre droit, puis le nœud",
          "correct": true,
          "feedback": "Bonne réponse : on visite le nœud **après** ses\nenfants. Très utile pour libérer la mémoire d'un\narbre (ses feuilles d'abord) ou évaluer une\nexpression arithmétique en notation postfixée.\n"
        },
        {
          "text": "Uniquement les feuilles, en ignorant les nœuds internes",
          "correct": false,
          "feedback": "Erreur : tous les nœuds sont visités, pas\nseulement les feuilles.\n"
        },
        {
          "text": "Les nœuds dans un ordre aléatoire, différent à chaque appel",
          "correct": false,
          "feedback": "Erreur : un parcours est déterministe.\n"
        },
        {
          "text": "D'abord le nœud courant, puis son sous-arbre gauche, puis son sous-arbre droit",
          "correct": false,
          "feedback": "Erreur : c'est le parcours préfixe.\n"
        }
      ],
      "explanation": "Application : pour calculer la **taille** d'un arbre\nou sa **hauteur** récursivement, on a besoin des\nrésultats des sous-arbres avant le nœud courant,\nc'est typiquement un parcours postfixe."
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "parcours-largeur"
      ],
      "title": "Parcours en largeur",
      "partie": "parcours",
      "statement": "Le parcours en **largeur** d'un arbre :",
      "options": [
        {
          "text": "Visite la branche gauche en entier avant la droite",
          "correct": false,
          "feedback": "Erreur : c'est plutôt un parcours en\n**profondeur** orienté vers la gauche.\n"
        },
        {
          "text": "Visite tous les nœuds à profondeur $0$, puis $1$, puis $2$, etc.",
          "correct": true,
          "feedback": "Bonne réponse : on parcourt niveau par niveau,\nde la racine vers les feuilles. Implémentation\nstandard : avec une **file**.\n"
        },
        {
          "text": "Visite uniquement les nœuds internes, sans passer par les feuilles",
          "correct": false,
          "feedback": "Erreur : tous les nœuds sont visités.\n"
        },
        {
          "text": "Évalue une expression arithmétique stockée dans l'arbre",
          "correct": false,
          "feedback": "Erreur : ce serait plutôt un parcours postfixe.\n"
        }
      ],
      "explanation": "Mémo : **largeur = file**, **profondeur = pile**\n(ou récursivité). Cette dualité est centrale dans\nles algorithmes sur les graphes, dont les\nparcours en largeur et en profondeur s'appuient\nsur ces deux structures."
    },
    {
      "id": "q10",
      "difficulty": 1,
      "skills": [
        "taille"
      ],
      "title": "Taille d'un arbre",
      "partie": "mesures",
      "statement": "La **taille** d'un arbre binaire est :",
      "options": [
        {
          "text": "Le nombre d'arêtes",
          "correct": false,
          "feedback": "Erreur : un arbre à $n$ nœuds a exactement\n$n - 1$ arêtes, donc ce n'est pas une mesure\nindépendante.\n"
        },
        {
          "text": "La hauteur du plus long chemin",
          "correct": false,
          "feedback": "Erreur : c'est la **hauteur**, pas la taille.\n"
        },
        {
          "text": "Le nombre total de nœuds",
          "correct": true,
          "feedback": "Bonne réponse : la taille compte tous les nœuds\n(internes et feuilles). Pour la calculer, un\nparcours récursif suffit : $T(\\text{vide}) = 0$ ;\n$T(\\text{nœud}) = 1 + T(\\text{gauche}) + T(\\text{droit})$.\n"
        },
        {
          "text": "Le nombre de feuilles",
          "correct": false,
          "feedback": "Erreur : c'est seulement une partie des nœuds.\n"
        }
      ],
      "explanation": "Relation utile : un arbre binaire de hauteur $h$ a\nau plus $2^{h+1} - 1$ nœuds. C'est le nombre maximum,\natteint quand l'arbre est **parfait** (tous les niveaux\nentièrement remplis, toutes les feuilles au même niveau)."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "implementation",
        "code"
      ],
      "title": "Implémentation Python",
      "partie": "implementation",
      "statement": "Pour un nœud d'arbre binaire, l'implémentation la plus\nclaire et la plus idiomatique en Python est :",
      "options": [
        {
          "text": "Une chaîne de caractères listant les valeurs des nœuds",
          "correct": false,
          "feedback": "Erreur : pas adapté à une structure récursive.\n"
        },
        {
          "text": "Un dictionnaire unique associant une clé entière à chaque nœud",
          "correct": false,
          "feedback": "Erreur : possible mais pas idiomatique. Une\nclasse dédiée est plus claire.\n"
        },
        {
          "text": "Une liste de longueur fixe `[valeur, gauche, droite]`",
          "correct": false,
          "feedback": "Erreur : possible, mais peu lisible. Une classe\ndédiée est plus claire.\n"
        },
        {
          "text": "Une classe avec trois attributs : `valeur`, `gauche`, `droit`",
          "correct": true,
          "feedback": "Bonne réponse : c'est l'approche orientée objet\nstandard, où `gauche` et `droit` valent soit\n`None`, soit un autre nœud. Exemple :\n\n```python\nclass Noeud:\n    def __init__(self, v, g=None, d=None):\n        self.valeur = v\n        self.gauche = g\n        self.droit = d\n```\n"
        }
      ],
      "explanation": "Convention : un sous-arbre vide est représenté par\n`None`. Cela simplifie la récursivité, le cas de\nbase est `if noeud is None: return ...`."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "calcul-hauteur"
      ],
      "title": "Calcul récursif de la hauteur",
      "partie": "mesures",
      "statement": "Quelle fonction Python calcule correctement la hauteur\nd'un arbre binaire (en nombre d'arêtes, $-1$ pour l'arbre\nvide) ?",
      "options": [
        {
          "text": "```python\ndef h(n):\n    return 1 + max(h(n.gauche), h(n.droit))\n```\n",
          "correct": false,
          "feedback": "Erreur : il manque le **cas de base**. La\nrécursion descend sur un sous-arbre vide et\n`n.gauche` est alors évalué sur `None`, ce qui\nlève `AttributeError`.\n"
        },
        {
          "text": "```python\ndef h(n):\n    if n is None: return 0\n    return 1 + h(n.gauche) + h(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : on **somme** les hauteurs, ce qui est\nincorrect. Il faut prendre le **maximum**.\n"
        },
        {
          "text": "```python\ndef h(n):\n    if n is None: return -1\n    return max(h(n.gauche), h(n.droit))\n```\n",
          "correct": false,
          "feedback": "Erreur : sans le `1 +`, rien ne compte les\narêtes descendues. La fonction renvoie $-1$\npour **tout** arbre, vide ou non.\n"
        },
        {
          "text": "```python\ndef h(n):\n    if n is None: return -1\n    return 1 + max(h(n.gauche), h(n.droit))\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : on prend la profondeur maximale\ndes deux sous-arbres et on ajoute $1$ (pour\nl'arête vers ce nœud). Convention : arbre vide\nde hauteur $-1$, racine seule de hauteur $0$.\n"
        }
      ],
      "explanation": "Convention alternative : compter en **nombre de nœuds** sur le chemin (cas vide → $0$). Adapter\nl'arithmétique en conséquence ($\\max + 1$ devient\n$\\max$ ou différent)."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "arbre-equilibre"
      ],
      "title": "Arbre équilibré",
      "partie": "vocabulaire",
      "statement": "Qu'est-ce qu'un arbre binaire **équilibré** ?",
      "options": [
        {
          "text": "Un arbre dont tous les nœuds internes possèdent exactement deux enfants, sans exception",
          "correct": false,
          "feedback": "Erreur : c'est un arbre **plein** (ou localement\ncomplet), pas équilibré.\n"
        },
        {
          "text": "Un arbre parfaitement symétrique, aux sous-arbres gauche et droit identiques",
          "correct": false,
          "feedback": "Erreur : un arbre équilibré n'est pas\nforcément symétrique. La symétrie est une\ncontrainte plus forte.\n"
        },
        {
          "text": "Un arbre où les hauteurs des deux sous-arbres de chaque nœud diffèrent d'au plus $1$",
          "correct": true,
          "feedback": "Bonne réponse : un arbre équilibré garde une hauteur de\nl'ordre de $\\log_2 n$ pour $n$ nœuds, ce qui rend la\nrecherche et l'insertion rapides dans un arbre binaire\nde recherche.\n"
        },
        {
          "text": "Un arbre où la racine se trouve au centre exact de la structure",
          "correct": false,
          "feedback": "Erreur : la racine est au sommet, pas au centre.\nLa notion d'« équilibre » est plus précise.\n"
        }
      ],
      "explanation": "Sans équilibrage, un arbre peut dégénérer en\n« peigne » (chaque nœud a un seul enfant) de\nhauteur $n$ : la recherche devient alors aussi lente\nqu'un parcours de liste."
    },
    {
      "id": "q14",
      "difficulty": 2,
      "skills": [
        "parcours",
        "code"
      ],
      "title": "Code de parcours préfixe",
      "partie": "parcours",
      "statement": "Quelle fonction Python affiche les valeurs d'un arbre\nbinaire en parcours **préfixe** ?",
      "options": [
        {
          "text": "```python\ndef parcours(n):\n    if n is None: return\n    print(n.valeur)\n    parcours(n.gauche)\n    parcours(n.droit)\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : on imprime le nœud **avant** ses\nenfants : c'est la définition même du parcours\npréfixe.\n"
        },
        {
          "text": "```python\ndef parcours(n):\n    print(n.valeur)\n    parcours(n.gauche)\n    parcours(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : il manque le **cas de base**\n`if n is None: return`. L'appel finit par\ndescendre sur `None` et lève\n`AttributeError` avant la fin du parcours.\n"
        },
        {
          "text": "```python\ndef parcours(n):\n    if n is None: return\n    parcours(n.gauche)\n    parcours(n.droit)\n    print(n.valeur)\n```\n",
          "correct": false,
          "feedback": "Erreur : c'est un parcours **postfixe** (nœud\naprès les enfants).\n"
        },
        {
          "text": "```python\ndef parcours(n):\n    if n is None: return\n    parcours(n.gauche)\n    print(n.valeur)\n    parcours(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : c'est le parcours **infixe**.\n"
        }
      ],
      "explanation": "Le seul changement entre les trois parcours en\nprofondeur est la **position** du `print` par rapport\naux deux appels récursifs. Très instructif à\nobserver."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "classe-noeud",
        "recursion",
        "somme"
      ],
      "title": "Somme des valeurs d'un arbre",
      "partie": "implementation",
      "statement": "Un arbre binaire est construit avec la classe `Noeud`, un sous-arbre\nvide valant `None` :\n```python\nclass Noeud:\n    def __init__(self, valeur, gauche, droit):\n        self.valeur = valeur\n        self.gauche = gauche\n        self.droit = droit\ndef somme(arbre):\n    if arbre is None:\n        return 0\n    return arbre.valeur + somme(arbre.gauche) + somme(arbre.droit)\na = Noeud(5, Noeud(3, None, Noeud(4, None, None)), Noeud(8, None, None))\n```\nQue renvoie `somme(a)` ?",
      "options": [
        {
          "text": "`20`",
          "correct": true,
          "feedback": "Bonne réponse : la fonction ajoute la valeur de chaque nœud à la\nsomme de ses deux sous-arbres, un sous-arbre vide comptant pour $0$.\nOn obtient $5 + 3 + 4 + 8 = 20$.\n"
        },
        {
          "text": "`12`",
          "correct": false,
          "feedback": "Erreur : $4 + 8 = 12$ ne compte que les feuilles. La fonction ajoute\naussi `arbre.valeur` pour chaque nœud interne, ici $5$ et $3$.\n"
        },
        {
          "text": "`16`",
          "correct": false,
          "feedback": "Erreur : $5 + 3 + 8 = 16$ s'arrête aux enfants de la racine. Les\nappels récursifs descendent jusqu'aux sous-arbres vides et comptent\naussi le nœud $4$, fils droit de $3$.\n"
        },
        {
          "text": "Une erreur, car certains sous-arbres valent `None`",
          "correct": false,
          "feedback": "Erreur : le cas de base `if arbre is None` traite justement les\nsous-arbres vides en renvoyant $0$, avant toute lecture de\n`arbre.valeur`.\n"
        }
      ],
      "explanation": "Une fonction récursive sur un arbre traite d'abord le cas de l'arbre\nvide, puis combine la valeur de la racine avec les résultats des deux\nsous-arbres. Ici la somme de toutes les valeurs vaut $20$.",
      "variants": [
        {
          "statement": "Un arbre binaire est construit avec la classe `Noeud`, un sous-arbre\nvide valant `None` :\n```python\nclass Noeud:\n    def __init__(self, valeur, gauche, droit):\n        self.valeur = valeur\n        self.gauche = gauche\n        self.droit = droit\ndef somme(arbre):\n    if arbre is None:\n        return 0\n    return arbre.valeur + somme(arbre.gauche) + somme(arbre.droit)\na = Noeud(5, Noeud(3, None, Noeud(4, None, None)), Noeud(8, None, None))\n```\nQue renvoie `somme(a)` ?",
          "options": [
            {
              "text": "`20`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction ajoute la valeur de chaque nœud à la\nsomme de ses deux sous-arbres, un sous-arbre vide comptant pour $0$.\nOn obtient $5 + 3 + 4 + 8 = 20$.\n"
            },
            {
              "text": "`12`",
              "correct": false,
              "feedback": "Erreur : $4 + 8 = 12$ ne compte que les feuilles. La fonction ajoute\naussi `arbre.valeur` pour chaque nœud interne, ici $5$ et $3$.\n"
            },
            {
              "text": "`16`",
              "correct": false,
              "feedback": "Erreur : $5 + 3 + 8 = 16$ s'arrête aux enfants de la racine. Les\nappels récursifs descendent jusqu'aux sous-arbres vides et comptent\naussi le nœud $4$, fils droit de $3$.\n"
            },
            {
              "text": "Une erreur, car certains sous-arbres valent `None`",
              "correct": false,
              "feedback": "Erreur : le cas de base `if arbre is None` traite justement les\nsous-arbres vides en renvoyant $0$, avant toute lecture de\n`arbre.valeur`.\n"
            }
          ],
          "explanation": "Une fonction récursive sur un arbre traite d'abord le cas de l'arbre\nvide, puis combine la valeur de la racine avec les résultats des deux\nsous-arbres. Ici la somme de toutes les valeurs vaut $20$."
        },
        {
          "statement": "Un arbre binaire est construit avec la classe `Noeud`, un sous-arbre\nvide valant `None` :\n```python\nclass Noeud:\n    def __init__(self, valeur, gauche, droit):\n        self.valeur = valeur\n        self.gauche = gauche\n        self.droit = droit\ndef somme(arbre):\n    if arbre is None:\n        return 0\n    return arbre.valeur + somme(arbre.gauche) + somme(arbre.droit)\na = Noeud(10, Noeud(2, None, Noeud(7, None, None)), Noeud(6, None, None))\n```\nQue renvoie `somme(a)` ?",
          "options": [
            {
              "text": "`25`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction ajoute la valeur de chaque nœud à la\nsomme de ses deux sous-arbres, un sous-arbre vide comptant pour $0$.\nOn obtient $10 + 2 + 7 + 6 = 25$.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : $7 + 6 = 13$ ne compte que les feuilles. La fonction ajoute\naussi `arbre.valeur` pour chaque nœud interne, ici $10$ et $2$.\n"
            },
            {
              "text": "`18`",
              "correct": false,
              "feedback": "Erreur : $10 + 2 + 6 = 18$ s'arrête aux enfants de la racine. Les\nappels récursifs descendent jusqu'aux sous-arbres vides et comptent\naussi le nœud $7$, fils droit de $2$.\n"
            },
            {
              "text": "Une erreur, car certains sous-arbres valent `None`",
              "correct": false,
              "feedback": "Erreur : le cas de base `if arbre is None` traite justement les\nsous-arbres vides en renvoyant $0$, avant toute lecture de\n`arbre.valeur`.\n"
            }
          ],
          "explanation": "Une fonction récursive sur un arbre traite d'abord le cas de l'arbre\nvide, puis combine la valeur de la racine avec les résultats des deux\nsous-arbres. Ici la somme de toutes les valeurs vaut $25$."
        },
        {
          "statement": "Un arbre binaire est construit avec la classe `Noeud`, un sous-arbre\nvide valant `None` :\n```python\nclass Noeud:\n    def __init__(self, valeur, gauche, droit):\n        self.valeur = valeur\n        self.gauche = gauche\n        self.droit = droit\ndef somme(arbre):\n    if arbre is None:\n        return 0\n    return arbre.valeur + somme(arbre.gauche) + somme(arbre.droit)\na = Noeud(1, Noeud(9, None, Noeud(2, None, None)), Noeud(5, None, None))\n```\nQue renvoie `somme(a)` ?",
          "options": [
            {
              "text": "`17`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction ajoute la valeur de chaque nœud à la\nsomme de ses deux sous-arbres, un sous-arbre vide comptant pour $0$.\nOn obtient $1 + 9 + 2 + 5 = 17$.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : $2 + 5 = 7$ ne compte que les feuilles. La fonction ajoute\naussi `arbre.valeur` pour chaque nœud interne, ici $1$ et $9$.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : $1 + 9 + 5 = 15$ s'arrête aux enfants de la racine. Les\nappels récursifs descendent jusqu'aux sous-arbres vides et comptent\naussi le nœud $2$, fils droit de $9$.\n"
            },
            {
              "text": "Une erreur, car certains sous-arbres valent `None`",
              "correct": false,
              "feedback": "Erreur : le cas de base `if arbre is None` traite justement les\nsous-arbres vides en renvoyant $0$, avant toute lecture de\n`arbre.valeur`.\n"
            }
          ],
          "explanation": "Une fonction récursive sur un arbre traite d'abord le cas de l'arbre\nvide, puis combine la valeur de la racine avec les résultats des deux\nsous-arbres. Ici la somme de toutes les valeurs vaut $17$."
        }
      ]
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "recursion",
        "propriete"
      ],
      "title": "Nombre de feuilles",
      "partie": "implementation",
      "statement": "Pour un arbre binaire **plein** (chaque nœud interne a\nexactement deux enfants), si $f$ est le nombre de\nfeuilles et $i$ le nombre de nœuds internes, quelle\nrelation a-t-on ?",
      "options": [
        {
          "text": "Aucune relation déterministe",
          "correct": false,
          "feedback": "Erreur : il existe bien une relation pour les\narbres pleins.\n"
        },
        {
          "text": "$f = i + 1$",
          "correct": true,
          "feedback": "Bonne réponse : par récurrence sur la taille.\nCas de base : un seul nœud (racine = feuille),\n$f = 1, i = 0$. Pour un arbre plus grand, chaque\nnouveau nœud interne ajoute une feuille (en\nremplaçant un fils null par un sous-arbre).\n"
        },
        {
          "text": "$f = i$",
          "correct": false,
          "feedback": "Erreur : la relation est différente. On peut\nmontrer $f = i + 1$ par récurrence.\n"
        },
        {
          "text": "$f = 2 \\cdot i$",
          "correct": false,
          "feedback": "Erreur : ne se vérifie pas.\n"
        }
      ],
      "explanation": "Cette relation s'utilise pour des comptages\nd'arbres dans les exercices. Elle vient d'une\nsymétrie structurelle : chaque nœud interne « remplace\n» une feuille par lui-même plus deux nouvelles\nfeuilles (delta de $+1$ feuille, $+1$ interne)."
    },
    {
      "id": "q17",
      "difficulty": 2,
      "skills": [
        "parcours-largeur-implementation"
      ],
      "title": "Implémenter un parcours en largeur",
      "partie": "parcours",
      "statement": "Pour implémenter un parcours en largeur d'un arbre\nbinaire en Python, on utilise généralement :",
      "options": [
        {
          "text": "Une file (`list` avec `append` et `pop(0)`)",
          "correct": true,
          "feedback": "Bonne réponse : on enfile la racine, puis tant\nque la file n'est pas vide on défile le nœud\ncourant (`pop(0)` retire le premier élément) et\non enfile ses deux enfants. La file assure le\ntraitement niveau par niveau.\n"
        },
        {
          "text": "Une simple variable mémorisant le nœud courant",
          "correct": false,
          "feedback": "Erreur : insuffisant pour stocker plusieurs\nnœuds en attente.\n"
        },
        {
          "text": "Une pile (`list` avec `append` et `pop`)",
          "correct": false,
          "feedback": "Erreur : la pile correspond au parcours en\n**profondeur**. Pour la largeur, c'est différent.\n"
        },
        {
          "text": "Un dictionnaire trié par valeur de nœud",
          "correct": false,
          "feedback": "Erreur : pas adapté.\n"
        }
      ],
      "explanation": "Code typique, avec une liste Python utilisée\ncomme file :\n\n```python\ndef parcours_largeur(racine):\n    if racine is None:\n        return\n    f = [racine]\n    while len(f) > 0:\n        n = f.pop(0)\n        print(n.valeur)\n        if n.gauche is not None:\n            f.append(n.gauche)\n        if n.droit is not None:\n            f.append(n.droit)\n```"
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "taille-borne"
      ],
      "title": "Borne du nombre de nœuds",
      "partie": "mesures",
      "statement": "Quel est le nombre **maximum** de nœuds d'un arbre\nbinaire de hauteur $h$, la hauteur étant comptée\nen nombre d'arêtes (un arbre réduit à sa racine a\nune hauteur 0) ?",
      "options": [
        {
          "text": "$h + 1$",
          "correct": false,
          "feedback": "Erreur : c'est le nombre **minimum** (arbre en\npeigne).\n"
        },
        {
          "text": "$h^2$",
          "correct": false,
          "feedback": "Erreur : la croissance n'est pas polynomiale\nmais exponentielle (en hauteur).\n"
        },
        {
          "text": "$2^h - 1$",
          "correct": false,
          "feedback": "Erreur d'une unité dans l'exposant : $2^h - 1$\nest le nombre maximal de nœuds d'un arbre de\nhauteur $h - 1$. Avec la convention « hauteur =\nnombre d'arêtes », un arbre parfait de hauteur\n$h$ possède $h + 1$ niveaux, soit $2^{h+1} - 1$\nnœuds.\n"
        },
        {
          "text": "$2^{h+1} - 1$",
          "correct": true,
          "feedback": "Bonne réponse : un arbre **parfait** de hauteur\n$h$ a $1 + 2 + 4 + \\ldots + 2^h = 2^{h+1} - 1$\nnœuds. C'est le maximum atteignable.\n"
        }
      ],
      "explanation": "Conséquence : pour avoir $n$ nœuds dans un arbre\néquilibré, la hauteur est de l'ordre de $\\log_2 n$.\nC'est ce qui rend les arbres de recherche si\nefficaces : opérations en $O(\\log n)$."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "recursion-symetrie"
      ],
      "title": "Arbre miroir",
      "partie": "implementation",
      "statement": "Pour calculer le **miroir** d'un arbre binaire\n(échanger gauche et droite à chaque nœud), une approche\nrécursive est :",
      "options": [
        {
          "text": "Échanger uniquement la racine de l'arbre avec sa dernière feuille",
          "correct": false,
          "feedback": "Erreur : pas suffisant. Il faut le faire à\n**chaque** nœud, récursivement.\n"
        },
        {
          "text": "Échanger les deux sous-arbres de chaque nœud, récursivement",
          "correct": true,
          "feedback": "Bonne réponse : on inverse à tous les niveaux.\nEn Python :\n\n```python\ndef miroir(n):\n    if n is None: return\n    n.gauche, n.droit = n.droit, n.gauche\n    miroir(n.gauche)\n    miroir(n.droit)\n```\n"
        },
        {
          "text": "Ne rien faire, l'arbre reste inchangé par symétrie",
          "correct": false,
          "feedback": "Erreur : ne donne pas le miroir.\n"
        },
        {
          "text": "Trier les valeurs des nœuds par ordre décroissant",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec le tri.\n"
        }
      ],
      "explanation": "C'est un exemple typique d'algorithme récursif\nsimple sur arbre. La récursion est naturelle car la\nstructure est elle-même récursive."
    },
    {
      "id": "q21",
      "difficulty": 3,
      "skills": [
        "analyse-complexite"
      ],
      "title": "Complexité de la recherche",
      "partie": "mesures",
      "statement": "Dans un arbre binaire **non ordonné** de $n$ nœuds, la\nrecherche d'une valeur a une complexité au pire de :",
      "options": [
        {
          "text": "$O(\\log n)$",
          "correct": false,
          "feedback": "Erreur : ce serait dans un arbre **ordonné**\néquilibré (arbre binaire de recherche\néquilibré). Sans ordre, on doit\nparcourir.\n"
        },
        {
          "text": "$O(n)$",
          "correct": true,
          "feedback": "Bonne réponse : sans propriété d'ordre, on doit\npotentiellement visiter tous les nœuds. Aucun\ngain par rapport à une liste.\n"
        },
        {
          "text": "$O(n^2)$",
          "correct": false,
          "feedback": "Erreur : excessif. Un simple parcours visite\nchaque nœud une fois, donc $O(n)$.\n"
        },
        {
          "text": "$O(\\sqrt{n})$",
          "correct": false,
          "feedback": "Erreur : aucune raison particulière.\n"
        }
      ],
      "explanation": "C'est précisément la motivation des **arbres binaires de recherche**, qui en ajoutant la\npropriété d'ordre, ramènent la recherche à\n$O(\\log n)$ en moyenne (et $O(\\log n)$ garanti si\néquilibré)."
    },
    {
      "id": "q24",
      "difficulty": 3,
      "skills": [
        "recursivite",
        "cas-de-base",
        "analyse-code"
      ],
      "title": "Comparer deux arbres récursivement",
      "partie": "implementation",
      "statement": "Avec la classe `Noeud` habituelle (attributs `valeur`, `gauche` et\n`droit`, un sous-arbre vide valant `None`), cette fonction teste si\ndeux arbres sont identiques :\n\n```python\ndef egaux(a, b):\n    if a is None and b is None:\n        return True\n    if a is None or b is None:\n        return False\n    return (a.valeur == b.valeur and egaux(a.gauche, b.gauche)\n            and egaux(a.droit, b.droit))\n```\n\nQue se passe-t-il si l'on supprime le second test,\n`if a is None or b is None`, et la ligne qui le suit ?",
      "options": [
        {
          "text": "La fonction reste correcte : ce second test était redondant",
          "correct": false,
          "feedback": "Erreur : le premier test ne traite que le cas où les deux arbres sont\nvides. Si un seul l'est, l'exécution atteint `a.valeur == b.valeur`\navec `None` d'un côté.\n"
        },
        {
          "text": "La fonction renvoie toujours `True`, les formes n'étant plus comparées",
          "correct": false,
          "feedback": "Erreur : la fonction compare toujours les valeurs et renvoie `False`\ndès que deux valeurs diffèrent. C'est le cas d'un seul sous-arbre\nvide qui n'est plus traité.\n"
        },
        {
          "text": "Une erreur survient quand un seul des deux sous-arbres comparés est vide",
          "correct": true,
          "feedback": "Bonne réponse : si `a` vaut `None` et pas `b`, ou l'inverse, le\npremier test échoue et Python lit l'attribut `valeur` de `None`, ce\nqui lève `AttributeError`. Si une différence de valeur est repérée\navant, `and` s'arrête et la fonction renvoie `False` sans erreur.\n"
        },
        {
          "text": "Les appels récursifs ne s'arrêtent plus et lèvent `RecursionError`",
          "correct": false,
          "feedback": "Erreur : chaque appel descend d'un niveau dans les deux arbres, qui\nsont finis. Les appels s'arrêtent soit sur deux sous-arbres vides,\nsoit sur une erreur dès qu'un seul l'est.\n"
        }
      ],
      "explanation": "Une fonction récursive sur deux arbres doit prévoir tous les cas de\nbase : les deux arbres vides, un seul vide. Oublier le cas d'un seul\narbre vide conduit à lire un attribut de `None`, ce qui provoque une\nerreur."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "synthese"
      ],
      "title": "Cas d'usage des arbres binaires",
      "partie": "mesures",
      "statement": "Lequel des cas suivants utilise typiquement un arbre\nbinaire ?",
      "options": [
        {
          "text": "Stocker une simple liste de courses du quotidien, sans aucun ordre particulier",
          "correct": false,
          "feedback": "Erreur : une liste plate suffit. Pas besoin\nd'arbre.\n"
        },
        {
          "text": "Échanger le contenu de deux variables d'un programme",
          "correct": false,
          "feedback": "L'échange de deux variables\nse fait avec une variable\ntemporaire (ou une affectation\nmultiple en Python). Cela n'a\naucun lien avec une structure\narborescente.\n"
        },
        {
          "text": "Compter le nombre total de mots dans un texte",
          "correct": false,
          "feedback": "Pour compter des mots,\nun simple compteur entier\nsuffit. Un arbre serait\ntotalement disproportionné\npour cette tâche.\n"
        },
        {
          "text": "Représenter une expression arithmétique ou un arbre de décision",
          "correct": true,
          "feedback": "Bonne réponse : ces cas exploitent la nature\nhiérarchique et/ou récursive de l'arbre. Autre\nusage majeur, l'index ordonné (arbre binaire\nde recherche), qui maintient un ensemble trié\navec insertion/suppression dynamiques.\n"
        }
      ],
      "explanation": "Autres usages : analyse syntaxique (arbres de\nsyntaxe abstraite), systèmes de fichiers (chaque\ndossier est un nœud), arbres de jeux (échecs, go),\nstructures de regroupement hiérarchique. Les arbres\nsont omniprésents en informatique."
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "taille-recursive"
      ],
      "title": "Calcul récursif de la taille",
      "partie": "mesures",
      "statement": "Quelle fonction Python calcule correctement la\n**taille** (nombre total de nœuds) d'un arbre\nbinaire ?",
      "options": [
        {
          "text": "```python\ndef taille(n):\n    if n is None:\n        return 0\n    return 1 + max(taille(n.gauche), taille(n.droit))\n```\n",
          "correct": false,
          "feedback": "Erreur : on prend ici le **maximum** au lieu de\nla **somme**. Le résultat correspond à la\nhauteur (en nombre de nœuds), pas à la taille.\n"
        },
        {
          "text": "```python\ndef taille(n):\n    if n is None:\n        return 0\n    return 1 + taille(n.gauche) + taille(n.droit)\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : on additionne $1$ (pour le nœud\ncourant) à la somme des tailles des deux\nsous-arbres. Le cas de base est l'arbre vide,\nde taille $0$. Récursion classique sur la\nstructure d'arbre, en $O(n)$.\n"
        },
        {
          "text": "```python\ndef taille(n):\n    if n is None:\n        return 1\n    return taille(n.gauche) + taille(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : on compte les **feuilles vides**\n(`None`) au lieu des nœuds. La taille d'un\narbre à un seul nœud serait $2$ au lieu de\n$1$, ce qui est faux.\n"
        },
        {
          "text": "```python\ndef taille(n):\n    if n is None:\n        return 0\n    return taille(n.gauche) + taille(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : on oublie de compter le nœud\ncourant (pas de `1 +`). La somme se réduit\nde proche en proche à des cas de base\nvalant $0$ : la fonction renvoie $0$ pour\n**tout** arbre.\n"
        }
      ],
      "explanation": "Cette structure de récursion (cas de base\n`None` → $0$, cas récursif $1 + $ somme des\nsous-arbres) est l'archétype de l'algorithme\nrécursif sur arbre binaire. Elle s'adapte à\nd'autres mesures (somme des valeurs, produit,\nmaximum, etc.) en changeant la combinaison."
    },
    {
      "id": "q27",
      "difficulty": 2,
      "skills": [
        "compter-feuilles"
      ],
      "title": "Compter les feuilles",
      "partie": "implementation",
      "statement": "Quelle fonction Python compte correctement le\nnombre de **feuilles** d'un arbre binaire ?",
      "options": [
        {
          "text": "```python\ndef feuilles(n):\n    if n is None:\n        return 1\n    return feuilles(n.gauche) + feuilles(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : on compte les positions vides\n(`None`), ce qui donne le double du nombre de\nfeuilles plus quelque chose pour les nœuds à\nun seul enfant. Pas la bonne mesure.\n"
        },
        {
          "text": "```python\ndef feuilles(n):\n    if n is None:\n        return 0\n    return feuilles(n.gauche) + feuilles(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : il manque le cas où le nœud est une\nfeuille. Cette fonction renverrait toujours\n$0$ car on ne compte jamais. Récursion\nstérile.\n"
        },
        {
          "text": "```python\ndef feuilles(n):\n    if n is None:\n        return 0\n    return 1 + feuilles(n.gauche) + feuilles(n.droit)\n```\n",
          "correct": false,
          "feedback": "Erreur : on ajoute $1$ pour **chaque** nœud,\nce qui compte la **taille totale** de l'arbre,\npas seulement les feuilles. Il faut distinguer\nles feuilles (sans enfant) des nœuds internes\n(au moins un enfant).\n"
        },
        {
          "text": "```python\ndef feuilles(n):\n    if n is None:\n        return 0\n    if n.gauche is None and n.droit is None:\n        return 1\n    return feuilles(n.gauche) + feuilles(n.droit)\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : trois cas. (1) Arbre vide :\naucune feuille. (2) Nœud sans enfant : une\nfeuille. (3) Nœud interne : on additionne les\nfeuilles des deux sous-arbres. C'est le\npatron classique de comptage récursif.\n"
        }
      ],
      "explanation": "Cas particulier dans le code : on doit reconnaître\nexplicitement les feuilles avec\n`n.gauche is None and n.droit is None`. C'est une\ndifférence importante par rapport à la fonction\n`taille`, qui se contente d'additionner sans\ndistinguer les feuilles."
    },
    {
      "id": "q28",
      "difficulty": 3,
      "skills": [
        "profondeur-recherche"
      ],
      "title": "Profondeur d'un nœud",
      "partie": "parcours",
      "statement": "Comment calculer la **profondeur** d'un nœud\ncontenant la valeur `cible` dans un arbre binaire\n(ou `-1` si la valeur n'est pas présente) ?",
      "options": [
        {
          "text": "```python\ndef profondeur(n, cible):\n    if n is None:\n        return -1\n    if n.valeur == cible:\n        return 0\n    g = profondeur(n.gauche, cible)\n    if g != -1:\n        return g + 1\n    return 1 + profondeur(n.droit, cible)\n```\n",
          "correct": false,
          "feedback": "Erreur : le cas « absent » n'est pas propagé.\nSi la cible n'est ni à gauche ni à droite, la\ndernière ligne renvoie $1 + (-1)$, c'est-à-dire\n$0$, que l'appelant prend pour une profondeur\nvalide. Une valeur absente de l'arbre reçoit\nalors une profondeur fantaisiste au lieu de\n`-1`.\n"
        },
        {
          "text": "```python\ndef profondeur(n, cible):\n    if n.valeur == cible:\n        return 0\n    return 1 + profondeur(n.gauche, cible)\n```\n",
          "correct": false,
          "feedback": "Erreur : on ne descend que dans le sous-arbre\n**gauche**, et on plante si on atteint un\nnœud `None` sans avoir trouvé la cible.\nL'arbre ne se réduit pas à sa branche gauche.\n"
        },
        {
          "text": "```python\ndef profondeur(n, cible):\n    if n is None:\n        return 0\n    if n.valeur == cible:\n        return 1\n    return profondeur(n.gauche, cible) + profondeur(n.droit, cible)\n```\n",
          "correct": false,
          "feedback": "Erreur : on **additionne** les résultats des\ndeux sous-arbres, ce qui n'a pas de sens pour\nune profondeur. De plus, on ne propage pas\nle compteur de profondeur, donc on ne peut\npas savoir à quelle distance se trouve la\ncible.\n"
        },
        {
          "text": "```python\ndef profondeur(n, cible, p=0):\n    if n is None:\n        return -1\n    if n.valeur == cible:\n        return p\n    g = profondeur(n.gauche, cible, p + 1)\n    if g != -1:\n        return g\n    return profondeur(n.droit, cible, p + 1)\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : on transmet la profondeur\ncourante via le paramètre `p`, qu'on incrémente\nà chaque descente récursive. On retourne `p`\ndès que la cible est trouvée. Si la recherche\ndans le sous-arbre gauche échoue (`-1`), on\nessaie le droit. Sinon on remonte `-1` (cible\nabsente).\n"
        }
      ],
      "explanation": "Variante intéressante : utiliser un parcours en\nlargeur avec une file qui contient les couples\n`(nœud, profondeur)`. Permet d'éviter la\nrécursion. Complexité dans les deux cas :\n`O(n)` au pire, où `n` est le nombre de nœuds."
    },
    {
      "id": "q29",
      "difficulty": 1,
      "skills": [
        "vocabulaire",
        "sous-arbres",
        "definition"
      ],
      "title": "Les sous-arbres d'un nœud",
      "partie": "vocabulaire",
      "statement": "Combien de sous-arbres un nœud d'arbre binaire possède-t-il ?",
      "options": [
        {
          "text": "Deux, le gauche et le droit, éventuellement vides",
          "correct": true,
          "feedback": "Bonne réponse : la définition récursive donne à chaque nœud\nexactement deux sous-arbres ordonnés ; une feuille a deux\nsous-arbres vides.\n"
        },
        {
          "text": "Un seul, le second n'étant qu'une option",
          "correct": false,
          "feedback": "Erreur : les deux positions, gauche et droite, existent\ntoujours, même vides.\n"
        },
        {
          "text": "Deux au minimum, un arbre binaire étant toujours complet",
          "correct": false,
          "feedback": "Erreur : rien n'impose que les deux sous-arbres soient non\nvides.\n"
        },
        {
          "text": "Autant que l'on veut, pourvu qu'ils soient ordonnés",
          "correct": false,
          "feedback": "Erreur : c'est la définition d'un arbre général, pas d'un\narbre binaire.\n"
        }
      ],
      "explanation": "Un arbre binaire est soit vide, soit un nœud muni d'un sous-arbre\ngauche et d'un sous-arbre droit, eux-mêmes binaires."
    },
    {
      "id": "q30",
      "difficulty": 2,
      "skills": [
        "vocabulaire",
        "filiforme",
        "hauteur"
      ],
      "title": "Un arbre réduit à une chaîne",
      "partie": "vocabulaire",
      "statement": "Dans un arbre binaire de $n$ nœuds, chaque nœud a au plus un\nenfant. Que peut-on dire de cet arbre ?",
      "options": [
        {
          "text": "Il est filiforme, de hauteur maximale pour $n$ nœuds",
          "correct": true,
          "feedback": "Bonne réponse : les nœuds forment une seule chaîne de la racine\nà l'unique feuille ; la hauteur est la plus grande possible,\ncomme pour une liste chaînée.\n"
        },
        {
          "text": "Il est équilibré, chaque nœud ayant au plus un enfant",
          "correct": false,
          "feedback": "Erreur : un arbre équilibré répartit les nœuds entre les deux\ncôtés ; ici tout est d'un seul côté à chaque niveau.\n"
        },
        {
          "text": "Ce n'est pas un arbre binaire, chaque nœud devant avoir deux enfants",
          "correct": false,
          "feedback": "Erreur : un sous-arbre vide est permis, l'arbre est bien\nbinaire.\n"
        },
        {
          "text": "Sa hauteur est de l'ordre de $\\log n$, comme toujours",
          "correct": false,
          "feedback": "Erreur : c'est la hauteur d'un arbre équilibré ; ici elle est\nde l'ordre de $n$.\n"
        }
      ],
      "explanation": "La forme d'un arbre binaire va de la chaîne, hauteur $n$, à l'arbre\néquilibré, hauteur $\\log n$ : c'est elle qui fixe le coût des\nparcours de la racine à une feuille."
    },
    {
      "id": "q31",
      "difficulty": 2,
      "skills": [
        "vocabulaire",
        "noeud-interne",
        "feuille",
        "calcul"
      ],
      "title": "Compter les nœuds internes",
      "partie": "vocabulaire",
      "statement": "Un arbre binaire compte $7$ nœuds, dont $4$ feuilles. Combien\na-t-il de nœuds internes ?",
      "options": [
        {
          "text": "$3$, les nœuds qui ne sont pas des feuilles",
          "correct": true,
          "feedback": "Bonne réponse : un nœud est soit une feuille, soit un nœud\ninterne ; $7 - 4 = 3$.\n"
        },
        {
          "text": "$4$, autant que de feuilles exactement",
          "correct": false,
          "feedback": "Erreur : rien n'impose l'égalité ; on retire les feuilles du\ntotal.\n"
        },
        {
          "text": "$6$, tous les nœuds sauf la racine",
          "correct": false,
          "feedback": "Erreur : la racine est un nœud interne dès qu'elle a un\nenfant, et les feuilles n'en sont pas.\n"
        },
        {
          "text": "$1$, la racine étant le seul nœud interne",
          "correct": false,
          "feedback": "Erreur : tout nœud ayant au moins un enfant est interne, pas\nseulement la racine.\n"
        }
      ],
      "explanation": "Feuilles et nœuds internes forment une partition des nœuds : les\ncompter l'un donne l'autre.",
      "variants": [
        {
          "statement": "Un arbre binaire compte $7$ nœuds, dont $4$ feuilles. Combien\na-t-il de nœuds internes ?",
          "options": [
            {
              "text": "$3$, les nœuds qui ne sont pas des feuilles",
              "correct": true,
              "feedback": "Bonne réponse : un nœud est soit une feuille, soit un nœud\ninterne ; $7 - 4 = 3$.\n"
            },
            {
              "text": "$4$, autant que de feuilles exactement",
              "correct": false,
              "feedback": "Erreur : rien n'impose l'égalité ; on retire les feuilles du\ntotal.\n"
            },
            {
              "text": "$6$, tous les nœuds sauf la racine",
              "correct": false,
              "feedback": "Erreur : la racine est un nœud interne dès qu'elle a un\nenfant, et les feuilles n'en sont pas.\n"
            },
            {
              "text": "$1$, la racine étant le seul nœud interne",
              "correct": false,
              "feedback": "Erreur : tout nœud ayant au moins un enfant est interne, pas\nseulement la racine.\n"
            }
          ],
          "explanation": "Feuilles et nœuds internes forment une partition des nœuds : les\ncompter l'un donne l'autre."
        },
        {
          "statement": "Un arbre binaire compte $10$ nœuds, dont $6$ feuilles. Combien\na-t-il de nœuds internes ?",
          "options": [
            {
              "text": "$4$, les nœuds qui ne sont pas des feuilles",
              "correct": true,
              "feedback": "Bonne réponse : un nœud est soit une feuille, soit un nœud\ninterne ; $10 - 6 = 4$.\n"
            },
            {
              "text": "$6$, autant que de feuilles exactement",
              "correct": false,
              "feedback": "Erreur : rien n'impose l'égalité ; on retire les feuilles du\ntotal.\n"
            },
            {
              "text": "$9$, tous les nœuds sauf la racine",
              "correct": false,
              "feedback": "Erreur : la racine est un nœud interne dès qu'elle a un\nenfant, et les feuilles n'en sont pas.\n"
            },
            {
              "text": "$1$, la racine étant le seul nœud interne",
              "correct": false,
              "feedback": "Erreur : tout nœud ayant au moins un enfant est interne, pas\nseulement la racine.\n"
            }
          ],
          "explanation": "Feuilles et nœuds internes forment une partition des nœuds : les\ncompter l'un donne l'autre."
        },
        {
          "statement": "Un arbre binaire compte $15$ nœuds, dont $8$ feuilles. Combien\na-t-il de nœuds internes ?",
          "options": [
            {
              "text": "$7$, les nœuds qui ne sont pas des feuilles",
              "correct": true,
              "feedback": "Bonne réponse : un nœud est soit une feuille, soit un nœud\ninterne ; $15 - 8 = 7$.\n"
            },
            {
              "text": "$8$, autant que de feuilles exactement",
              "correct": false,
              "feedback": "Erreur : rien n'impose l'égalité ; on retire les feuilles du\ntotal.\n"
            },
            {
              "text": "$14$, tous les nœuds sauf la racine",
              "correct": false,
              "feedback": "Erreur : la racine est un nœud interne dès qu'elle a un\nenfant, et les feuilles n'en sont pas.\n"
            },
            {
              "text": "$1$, la racine étant le seul nœud interne",
              "correct": false,
              "feedback": "Erreur : tout nœud ayant au moins un enfant est interne, pas\nseulement la racine.\n"
            }
          ],
          "explanation": "Feuilles et nœuds internes forment une partition des nœuds : les\ncompter l'un donne l'autre."
        }
      ]
    },
    {
      "id": "q32",
      "difficulty": 1,
      "skills": [
        "vocabulaire",
        "arbre-vide",
        "recursion"
      ],
      "title": "L'arbre vide",
      "partie": "vocabulaire",
      "statement": "L'arbre vide, sans aucun nœud, est-il un arbre binaire ?",
      "options": [
        {
          "text": "Oui, c'est le cas de base des définitions récursives",
          "correct": true,
          "feedback": "Bonne réponse : tout sous-arbre absent est un arbre vide, et\nles fonctions récursives sur les arbres commencent par le\ntraiter.\n"
        },
        {
          "text": "Non, un arbre a toujours au moins une racine",
          "correct": false,
          "feedback": "Erreur : sans arbre vide, impossible de dire ce qu'est le\nsous-arbre gauche d'une feuille.\n"
        },
        {
          "text": "Oui, mais seulement comme sous-arbre d'une feuille",
          "correct": false,
          "feedback": "Erreur : l'arbre vide existe aussi seul, par exemple avant la\npremière insertion.\n"
        },
        {
          "text": "Non, il s'agit d'une liste vide et non d'un arbre",
          "correct": false,
          "feedback": "Erreur : la structure vide de chaque type existe, liste vide,\npile vide, arbre vide.\n"
        }
      ],
      "explanation": "Taille nulle, aucune feuille : l'arbre vide est le point de départ\nde toutes les mesures récursives."
    },
    {
      "id": "q33",
      "difficulty": 2,
      "skills": [
        "implementation",
        "tuples",
        "acces"
      ],
      "title": "Un arbre représenté par des tuples imbriqués",
      "partie": "implementation",
      "statement": "Un arbre est représenté par le tuple `(gauche, valeur, droit)`,\nun sous-arbre vide étant `None`. Que vaut `a[2][1]` ?\n```python\na = ((None, 2, None), 5, (None, 8, None))\n```",
      "options": [
        {
          "text": "`8`, la valeur du fils droit",
          "correct": true,
          "feedback": "Bonne réponse : `a[2]` est le sous-arbre droit\n`(None, 8, None)`, et son élément d'indice $1$ est sa\nvaleur, `8`.\n"
        },
        {
          "text": "`5`, la valeur de la racine",
          "correct": false,
          "feedback": "Erreur : la valeur de la racine est `a[1]`.\n"
        },
        {
          "text": "`2`, la valeur du fils gauche",
          "correct": false,
          "feedback": "Erreur : le fils gauche est `a[0]`.\n"
        },
        {
          "text": "Une erreur, un tuple ne s'indexant pas deux fois",
          "correct": false,
          "feedback": "Erreur : `a[2]` est lui-même un tuple, on peut l'indexer à son\ntour.\n"
        }
      ],
      "explanation": "Avec des tuples, descendre dans l'arbre revient à enchaîner les\nindices : $0$ pour la gauche, $1$ pour la valeur, $2$ pour la\ndroite.",
      "variants": [
        {
          "statement": "Un arbre est représenté par le tuple `(gauche, valeur, droit)`,\nun sous-arbre vide étant `None`. Que vaut `a[2][1]` ?\n```python\na = ((None, 2, None), 5, (None, 8, None))\n```",
          "options": [
            {
              "text": "`8`, la valeur du fils droit",
              "correct": true,
              "feedback": "Bonne réponse : `a[2]` est le sous-arbre droit\n`(None, 8, None)`, et son élément d'indice $1$ est sa\nvaleur, `8`.\n"
            },
            {
              "text": "`5`, la valeur de la racine",
              "correct": false,
              "feedback": "Erreur : la valeur de la racine est `a[1]`.\n"
            },
            {
              "text": "`2`, la valeur du fils gauche",
              "correct": false,
              "feedback": "Erreur : le fils gauche est `a[0]`.\n"
            },
            {
              "text": "Une erreur, un tuple ne s'indexant pas deux fois",
              "correct": false,
              "feedback": "Erreur : `a[2]` est lui-même un tuple, on peut l'indexer à son\ntour.\n"
            }
          ],
          "explanation": "Avec des tuples, descendre dans l'arbre revient à enchaîner les\nindices : $0$ pour la gauche, $1$ pour la valeur, $2$ pour la\ndroite."
        },
        {
          "statement": "Un arbre est représenté par le tuple `(gauche, valeur, droit)`,\nun sous-arbre vide étant `None`. Que vaut `a[2][1]` ?\n```python\na = ((None, 1, None), 4, (None, 9, None))\n```",
          "options": [
            {
              "text": "`9`, la valeur du fils droit",
              "correct": true,
              "feedback": "Bonne réponse : `a[2]` est le sous-arbre droit\n`(None, 9, None)`, et son élément d'indice $1$ est sa\nvaleur, `9`.\n"
            },
            {
              "text": "`4`, la valeur de la racine",
              "correct": false,
              "feedback": "Erreur : la valeur de la racine est `a[1]`.\n"
            },
            {
              "text": "`1`, la valeur du fils gauche",
              "correct": false,
              "feedback": "Erreur : le fils gauche est `a[0]`.\n"
            },
            {
              "text": "Une erreur, un tuple ne s'indexant pas deux fois",
              "correct": false,
              "feedback": "Erreur : `a[2]` est lui-même un tuple, on peut l'indexer à son\ntour.\n"
            }
          ],
          "explanation": "Avec des tuples, descendre dans l'arbre revient à enchaîner les\nindices : $0$ pour la gauche, $1$ pour la valeur, $2$ pour la\ndroite."
        },
        {
          "statement": "Un arbre est représenté par le tuple `(gauche, valeur, droit)`,\nun sous-arbre vide étant `None`. Que vaut `a[2][1]` ?\n```python\na = ((None, 3, None), 6, (None, 7, None))\n```",
          "options": [
            {
              "text": "`7`, la valeur du fils droit",
              "correct": true,
              "feedback": "Bonne réponse : `a[2]` est le sous-arbre droit\n`(None, 7, None)`, et son élément d'indice $1$ est sa\nvaleur, `7`.\n"
            },
            {
              "text": "`6`, la valeur de la racine",
              "correct": false,
              "feedback": "Erreur : la valeur de la racine est `a[1]`.\n"
            },
            {
              "text": "`3`, la valeur du fils gauche",
              "correct": false,
              "feedback": "Erreur : le fils gauche est `a[0]`.\n"
            },
            {
              "text": "Une erreur, un tuple ne s'indexant pas deux fois",
              "correct": false,
              "feedback": "Erreur : `a[2]` est lui-même un tuple, on peut l'indexer à son\ntour.\n"
            }
          ],
          "explanation": "Avec des tuples, descendre dans l'arbre revient à enchaîner les\nindices : $0$ pour la gauche, $1$ pour la valeur, $2$ pour la\ndroite."
        }
      ]
    },
    {
      "id": "q34",
      "difficulty": 2,
      "skills": [
        "implementation",
        "feuille",
        "classe"
      ],
      "title": "Reconnaître une feuille",
      "partie": "implementation",
      "statement": "Un nœud est un objet de classe `Noeud` avec les attributs\n`valeur`, `gauche` et `droit`, un sous-arbre vide étant `None`.\nQuelle expression indique que `n` est une feuille ?",
      "options": [
        {
          "text": "`n.gauche is None and n.droit is None`",
          "correct": true,
          "feedback": "Bonne réponse : une feuille n'a aucun enfant, les deux liens\ndoivent être absents.\n"
        },
        {
          "text": "`n.gauche is None or n.droit is None`",
          "correct": false,
          "feedback": "Erreur : un nœud avec un seul enfant vérifie cette condition\nsans être une feuille.\n"
        },
        {
          "text": "`n.valeur is None`, la feuille ne portant rien",
          "correct": false,
          "feedback": "Erreur : la valeur d'une feuille est une donnée ordinaire.\n"
        },
        {
          "text": "`n is None`, le nœud étant au bout de l'arbre",
          "correct": false,
          "feedback": "Erreur : `None` est l'arbre vide, pas une feuille.\n"
        }
      ],
      "explanation": "Feuille et arbre vide se distinguent : la feuille est un nœud sans\nenfant, l'arbre vide n'est pas un nœud."
    },
    {
      "id": "q35",
      "difficulty": 3,
      "skills": [
        "implementation",
        "lecture-de-code",
        "deux-enfants"
      ],
      "title": "Lire une fonction récursive sur un arbre",
      "partie": "implementation",
      "statement": "Que calcule cette fonction, pour un arbre de nœuds `Noeud` dont\nles sous-arbres vides sont `None` ?\n```python\ndef compte(a):\n    if a is None:\n        return 0\n    n = compte(a.gauche) + compte(a.droit)\n    if a.gauche is not None and a.droit is not None:\n        n = n + 1\n    return n\n```",
      "options": [
        {
          "text": "Le nombre de nœuds ayant exactement deux enfants",
          "correct": true,
          "feedback": "Bonne réponse : chaque nœud ajoute $1$ au total de ses\nsous-arbres seulement si ses deux enfants existent.\n"
        },
        {
          "text": "Le nombre de feuilles, nœuds sans enfant",
          "correct": false,
          "feedback": "Erreur : une feuille a ses deux liens à `None`, elle n'ajoute\nrien.\n"
        },
        {
          "text": "La taille de l'arbre, son nombre de nœuds",
          "correct": false,
          "feedback": "Erreur : la taille ajouterait $1$ pour tout nœud, sans\ncondition.\n"
        },
        {
          "text": "Le nombre de nœuds internes, à un ou deux enfants",
          "correct": false,
          "feedback": "Erreur : un nœud à un seul enfant est interne mais n'est pas\ncompté.\n"
        }
      ],
      "explanation": "Lire une fonction récursive sur un arbre, c'est repérer ce qui est\najouté à chaque nœud et à quelle condition."
    },
    {
      "id": "q36",
      "difficulty": 2,
      "skills": [
        "parcours",
        "infixe",
        "trace"
      ],
      "title": "Ordre infixe d'un arbre décrit en mots",
      "partie": "parcours",
      "statement": "La racine porte `A`. Son fils gauche `B` a deux enfants,\n`D` à gauche et `E` à droite. Son fils droit `C` a un\nseul enfant, `F`, à gauche. Quel est le parcours infixe ?",
      "options": [
        {
          "text": "`D B E A F C`",
          "correct": true,
          "feedback": "Bonne réponse : infixe signifie sous-arbre gauche, nœud,\nsous-arbre droit, appliqué récursivement : `D B E`,\npuis `A`, puis `F C`.\n"
        },
        {
          "text": "`A B D E C F`",
          "correct": false,
          "feedback": "Erreur : c'est le parcours préfixe, le nœud avant ses\nsous-arbres.\n"
        },
        {
          "text": "`D E B F C A`",
          "correct": false,
          "feedback": "Erreur : c'est le parcours postfixe, le nœud après ses\nsous-arbres.\n"
        },
        {
          "text": "`A B C D E F`",
          "correct": false,
          "feedback": "Erreur : c'est le parcours en largeur, niveau par niveau.\n"
        }
      ],
      "explanation": "Les trois parcours en profondeur ne diffèrent que par la place du\nnœud par rapport à ses deux sous-arbres.",
      "variants": [
        {
          "statement": "La racine porte `A`. Son fils gauche `B` a deux enfants,\n`D` à gauche et `E` à droite. Son fils droit `C` a un\nseul enfant, `F`, à gauche. Quel est le parcours infixe ?",
          "options": [
            {
              "text": "`D B E A F C`",
              "correct": true,
              "feedback": "Bonne réponse : infixe signifie sous-arbre gauche, nœud,\nsous-arbre droit, appliqué récursivement : `D B E`,\npuis `A`, puis `F C`.\n"
            },
            {
              "text": "`A B D E C F`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours préfixe, le nœud avant ses\nsous-arbres.\n"
            },
            {
              "text": "`D E B F C A`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours postfixe, le nœud après ses\nsous-arbres.\n"
            },
            {
              "text": "`A B C D E F`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours en largeur, niveau par niveau.\n"
            }
          ],
          "explanation": "Les trois parcours en profondeur ne diffèrent que par la place du\nnœud par rapport à ses deux sous-arbres."
        },
        {
          "statement": "La racine porte `M`. Son fils gauche `K` a deux enfants,\n`J` à gauche et `L` à droite. Son fils droit `P` a un\nseul enfant, `N`, à gauche. Quel est le parcours infixe ?",
          "options": [
            {
              "text": "`J K L M N P`",
              "correct": true,
              "feedback": "Bonne réponse : infixe signifie sous-arbre gauche, nœud,\nsous-arbre droit, appliqué récursivement : `J K L`,\npuis `M`, puis `N P`.\n"
            },
            {
              "text": "`M K J L P N`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours préfixe, le nœud avant ses\nsous-arbres.\n"
            },
            {
              "text": "`J L K N P M`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours postfixe, le nœud après ses\nsous-arbres.\n"
            },
            {
              "text": "`M K P J L N`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours en largeur, niveau par niveau.\n"
            }
          ],
          "explanation": "Les trois parcours en profondeur ne diffèrent que par la place du\nnœud par rapport à ses deux sous-arbres."
        },
        {
          "statement": "La racine porte `5`. Son fils gauche `3` a deux enfants,\n`1` à gauche et `4` à droite. Son fils droit `8` a un\nseul enfant, `7`, à gauche. Quel est le parcours infixe ?",
          "options": [
            {
              "text": "`1 3 4 5 7 8`",
              "correct": true,
              "feedback": "Bonne réponse : infixe signifie sous-arbre gauche, nœud,\nsous-arbre droit, appliqué récursivement : `1 3 4`,\npuis `5`, puis `7 8`.\n"
            },
            {
              "text": "`5 3 1 4 8 7`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours préfixe, le nœud avant ses\nsous-arbres.\n"
            },
            {
              "text": "`1 4 3 7 8 5`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours postfixe, le nœud après ses\nsous-arbres.\n"
            },
            {
              "text": "`5 3 8 1 4 7`",
              "correct": false,
              "feedback": "Erreur : c'est le parcours en largeur, niveau par niveau.\n"
            }
          ],
          "explanation": "Les trois parcours en profondeur ne diffèrent que par la place du\nnœud par rapport à ses deux sous-arbres."
        }
      ]
    },
    {
      "id": "q37",
      "difficulty": 3,
      "skills": [
        "parcours",
        "prefixe",
        "infixe",
        "reconstruction"
      ],
      "title": "Retrouver un arbre à partir de deux parcours",
      "partie": "parcours",
      "statement": "Un arbre binaire de trois nœuds a pour parcours préfixe\n`A B C` et pour parcours infixe `B A C`. Quel est\ncet arbre ?",
      "options": [
        {
          "text": "Racine `A`, fils gauche `B`, fils droit `C`",
          "correct": true,
          "feedback": "Bonne réponse : le préfixe commence par la racine, `A` ; dans\nl'infixe, ce qui précède `A` est à gauche, `B`, et ce qui\nsuit est à droite, `C`.\n"
        },
        {
          "text": "Racine `B`, fils gauche `A`, fils droit `C`",
          "correct": false,
          "feedback": "Erreur : le premier nœud du parcours préfixe est la racine,\n`A`.\n"
        },
        {
          "text": "Racine `A`, fils gauche `C`, fils droit `B`",
          "correct": false,
          "feedback": "Erreur : le parcours infixe placerait alors `C` avant `A`.\n"
        },
        {
          "text": "Racine `C`, fils gauche `B`, fils droit `A`",
          "correct": false,
          "feedback": "Erreur : `C` est le dernier du préfixe, il ne peut pas être\nla racine.\n"
        }
      ],
      "explanation": "Le préfixe donne la racine, l'infixe sépare ce qui est à gauche de\nce qui est à droite : les deux parcours ensemble déterminent\nl'arbre.",
      "variants": [
        {
          "statement": "Un arbre binaire de trois nœuds a pour parcours préfixe\n`A B C` et pour parcours infixe `B A C`. Quel est\ncet arbre ?",
          "options": [
            {
              "text": "Racine `A`, fils gauche `B`, fils droit `C`",
              "correct": true,
              "feedback": "Bonne réponse : le préfixe commence par la racine, `A` ; dans\nl'infixe, ce qui précède `A` est à gauche, `B`, et ce qui\nsuit est à droite, `C`.\n"
            },
            {
              "text": "Racine `B`, fils gauche `A`, fils droit `C`",
              "correct": false,
              "feedback": "Erreur : le premier nœud du parcours préfixe est la racine,\n`A`.\n"
            },
            {
              "text": "Racine `A`, fils gauche `C`, fils droit `B`",
              "correct": false,
              "feedback": "Erreur : le parcours infixe placerait alors `C` avant `A`.\n"
            },
            {
              "text": "Racine `C`, fils gauche `B`, fils droit `A`",
              "correct": false,
              "feedback": "Erreur : `C` est le dernier du préfixe, il ne peut pas être\nla racine.\n"
            }
          ],
          "explanation": "Le préfixe donne la racine, l'infixe sépare ce qui est à gauche de\nce qui est à droite : les deux parcours ensemble déterminent\nl'arbre."
        },
        {
          "statement": "Un arbre binaire de trois nœuds a pour parcours préfixe\n`X Y Z` et pour parcours infixe `Y X Z`. Quel est\ncet arbre ?",
          "options": [
            {
              "text": "Racine `X`, fils gauche `Y`, fils droit `Z`",
              "correct": true,
              "feedback": "Bonne réponse : le préfixe commence par la racine, `X` ; dans\nl'infixe, ce qui précède `X` est à gauche, `Y`, et ce qui\nsuit est à droite, `Z`.\n"
            },
            {
              "text": "Racine `Y`, fils gauche `X`, fils droit `Z`",
              "correct": false,
              "feedback": "Erreur : le premier nœud du parcours préfixe est la racine,\n`X`.\n"
            },
            {
              "text": "Racine `X`, fils gauche `Z`, fils droit `Y`",
              "correct": false,
              "feedback": "Erreur : le parcours infixe placerait alors `Z` avant `X`.\n"
            },
            {
              "text": "Racine `Z`, fils gauche `Y`, fils droit `X`",
              "correct": false,
              "feedback": "Erreur : `Z` est le dernier du préfixe, il ne peut pas être\nla racine.\n"
            }
          ],
          "explanation": "Le préfixe donne la racine, l'infixe sépare ce qui est à gauche de\nce qui est à droite : les deux parcours ensemble déterminent\nl'arbre."
        },
        {
          "statement": "Un arbre binaire de trois nœuds a pour parcours préfixe\n`7 2 9` et pour parcours infixe `2 7 9`. Quel est\ncet arbre ?",
          "options": [
            {
              "text": "Racine `7`, fils gauche `2`, fils droit `9`",
              "correct": true,
              "feedback": "Bonne réponse : le préfixe commence par la racine, `7` ; dans\nl'infixe, ce qui précède `7` est à gauche, `2`, et ce qui\nsuit est à droite, `9`.\n"
            },
            {
              "text": "Racine `2`, fils gauche `7`, fils droit `9`",
              "correct": false,
              "feedback": "Erreur : le premier nœud du parcours préfixe est la racine,\n`7`.\n"
            },
            {
              "text": "Racine `7`, fils gauche `9`, fils droit `2`",
              "correct": false,
              "feedback": "Erreur : le parcours infixe placerait alors `9` avant `7`.\n"
            },
            {
              "text": "Racine `9`, fils gauche `2`, fils droit `7`",
              "correct": false,
              "feedback": "Erreur : `9` est le dernier du préfixe, il ne peut pas être\nla racine.\n"
            }
          ],
          "explanation": "Le préfixe donne la racine, l'infixe sépare ce qui est à gauche de\nce qui est à droite : les deux parcours ensemble déterminent\nl'arbre."
        }
      ]
    },
    {
      "id": "q38",
      "difficulty": 2,
      "skills": [
        "mesures",
        "arbre-parfait",
        "feuilles",
        "calcul"
      ],
      "title": "Les feuilles d'un arbre aux niveaux pleins",
      "partie": "mesures",
      "statement": "Un arbre binaire a $3$ niveaux, tous pleins. Combien de feuilles\ncompte-t-il ?",
      "options": [
        {
          "text": "$4$, le dernier niveau entier",
          "correct": true,
          "feedback": "Bonne réponse : le niveau $k$ contient $2^{k-1}$ nœuds ; les\nfeuilles sont les $2^{2} = 4$ nœuds du dernier niveau.\n"
        },
        {
          "text": "$7$, tous les nœuds de l'arbre",
          "correct": false,
          "feedback": "Erreur : $7$ est le nombre total de nœuds, dont seuls ceux du\ndernier niveau sont des feuilles.\n"
        },
        {
          "text": "$8$, le double du dernier niveau",
          "correct": false,
          "feedback": "Erreur : $2^{3}$ serait le niveau suivant, qui n'existe pas.\n"
        },
        {
          "text": "$3$, une seule par niveau",
          "correct": false,
          "feedback": "Erreur : les feuilles sont toutes au dernier niveau, pas une\npar niveau.\n"
        }
      ],
      "explanation": "Dans un arbre aux niveaux pleins, chaque niveau double le\nprécédent : la moitié des nœuds, à un près, sont des feuilles.",
      "variants": [
        {
          "statement": "Un arbre binaire a $3$ niveaux, tous pleins. Combien de feuilles\ncompte-t-il ?",
          "options": [
            {
              "text": "$4$, le dernier niveau entier",
              "correct": true,
              "feedback": "Bonne réponse : le niveau $k$ contient $2^{k-1}$ nœuds ; les\nfeuilles sont les $2^{2} = 4$ nœuds du dernier niveau.\n"
            },
            {
              "text": "$7$, tous les nœuds de l'arbre",
              "correct": false,
              "feedback": "Erreur : $7$ est le nombre total de nœuds, dont seuls ceux du\ndernier niveau sont des feuilles.\n"
            },
            {
              "text": "$8$, le double du dernier niveau",
              "correct": false,
              "feedback": "Erreur : $2^{3}$ serait le niveau suivant, qui n'existe pas.\n"
            },
            {
              "text": "$3$, une seule par niveau",
              "correct": false,
              "feedback": "Erreur : les feuilles sont toutes au dernier niveau, pas une\npar niveau.\n"
            }
          ],
          "explanation": "Dans un arbre aux niveaux pleins, chaque niveau double le\nprécédent : la moitié des nœuds, à un près, sont des feuilles."
        },
        {
          "statement": "Un arbre binaire a $4$ niveaux, tous pleins. Combien de feuilles\ncompte-t-il ?",
          "options": [
            {
              "text": "$8$, le dernier niveau entier",
              "correct": true,
              "feedback": "Bonne réponse : le niveau $k$ contient $2^{k-1}$ nœuds ; les\nfeuilles sont les $2^{3} = 8$ nœuds du dernier niveau.\n"
            },
            {
              "text": "$15$, tous les nœuds de l'arbre",
              "correct": false,
              "feedback": "Erreur : $15$ est le nombre total de nœuds, dont seuls ceux du\ndernier niveau sont des feuilles.\n"
            },
            {
              "text": "$16$, le double du dernier niveau",
              "correct": false,
              "feedback": "Erreur : $2^{4}$ serait le niveau suivant, qui n'existe pas.\n"
            },
            {
              "text": "$4$, une seule par niveau",
              "correct": false,
              "feedback": "Erreur : les feuilles sont toutes au dernier niveau, pas une\npar niveau.\n"
            }
          ],
          "explanation": "Dans un arbre aux niveaux pleins, chaque niveau double le\nprécédent : la moitié des nœuds, à un près, sont des feuilles."
        },
        {
          "statement": "Un arbre binaire a $5$ niveaux, tous pleins. Combien de feuilles\ncompte-t-il ?",
          "options": [
            {
              "text": "$16$, le dernier niveau entier",
              "correct": true,
              "feedback": "Bonne réponse : le niveau $k$ contient $2^{k-1}$ nœuds ; les\nfeuilles sont les $2^{4} = 16$ nœuds du dernier niveau.\n"
            },
            {
              "text": "$31$, tous les nœuds de l'arbre",
              "correct": false,
              "feedback": "Erreur : $31$ est le nombre total de nœuds, dont seuls ceux du\ndernier niveau sont des feuilles.\n"
            },
            {
              "text": "$32$, le double du dernier niveau",
              "correct": false,
              "feedback": "Erreur : $2^{5}$ serait le niveau suivant, qui n'existe pas.\n"
            },
            {
              "text": "$5$, une seule par niveau",
              "correct": false,
              "feedback": "Erreur : les feuilles sont toutes au dernier niveau, pas une\npar niveau.\n"
            }
          ],
          "explanation": "Dans un arbre aux niveaux pleins, chaque niveau double le\nprécédent : la moitié des nœuds, à un près, sont des feuilles."
        }
      ]
    },
    {
      "id": "q39",
      "difficulty": 3,
      "skills": [
        "mesures",
        "noeuds-internes",
        "feuilles",
        "recurrence"
      ],
      "title": "Feuilles et nœuds à deux enfants",
      "partie": "mesures",
      "statement": "Dans un arbre binaire, chaque nœud interne a exactement deux\nenfants. L'arbre compte $4$ nœuds internes. Combien a-t-il de\nfeuilles ?",
      "options": [
        {
          "text": "$5$, une de plus que de nœuds internes",
          "correct": true,
          "feedback": "Bonne réponse : l'arbre réduit à une feuille vérifie la\nrelation ; remplacer une feuille par un nœud à deux enfants\najoute un interne et une feuille nette. D'où $4 + 1 = 5$.\n"
        },
        {
          "text": "$8$, deux feuilles par nœud interne",
          "correct": false,
          "feedback": "Erreur : les enfants d'un nœud interne sont souvent eux-mêmes\ninternes, pas des feuilles.\n"
        },
        {
          "text": "$4$, autant que de nœuds internes",
          "correct": false,
          "feedback": "Erreur : il y en a toujours une de plus.\n"
        },
        {
          "text": "$3$, une de moins que de nœuds internes",
          "correct": false,
          "feedback": "Erreur : le sens de la différence est inversé.\n"
        }
      ],
      "explanation": "Dans un arbre binaire où tout nœud interne a deux enfants, le\nnombre de feuilles dépasse de un le nombre de nœuds internes : un\nrésultat qui se prouve par récurrence sur la taille.",
      "variants": [
        {
          "statement": "Dans un arbre binaire, chaque nœud interne a exactement deux\nenfants. L'arbre compte $4$ nœuds internes. Combien a-t-il de\nfeuilles ?",
          "options": [
            {
              "text": "$5$, une de plus que de nœuds internes",
              "correct": true,
              "feedback": "Bonne réponse : l'arbre réduit à une feuille vérifie la\nrelation ; remplacer une feuille par un nœud à deux enfants\najoute un interne et une feuille nette. D'où $4 + 1 = 5$.\n"
            },
            {
              "text": "$8$, deux feuilles par nœud interne",
              "correct": false,
              "feedback": "Erreur : les enfants d'un nœud interne sont souvent eux-mêmes\ninternes, pas des feuilles.\n"
            },
            {
              "text": "$4$, autant que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : il y en a toujours une de plus.\n"
            },
            {
              "text": "$3$, une de moins que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : le sens de la différence est inversé.\n"
            }
          ],
          "explanation": "Dans un arbre binaire où tout nœud interne a deux enfants, le\nnombre de feuilles dépasse de un le nombre de nœuds internes : un\nrésultat qui se prouve par récurrence sur la taille."
        },
        {
          "statement": "Dans un arbre binaire, chaque nœud interne a exactement deux\nenfants. L'arbre compte $7$ nœuds internes. Combien a-t-il de\nfeuilles ?",
          "options": [
            {
              "text": "$8$, une de plus que de nœuds internes",
              "correct": true,
              "feedback": "Bonne réponse : l'arbre réduit à une feuille vérifie la\nrelation ; remplacer une feuille par un nœud à deux enfants\najoute un interne et une feuille nette. D'où $7 + 1 = 8$.\n"
            },
            {
              "text": "$14$, deux feuilles par nœud interne",
              "correct": false,
              "feedback": "Erreur : les enfants d'un nœud interne sont souvent eux-mêmes\ninternes, pas des feuilles.\n"
            },
            {
              "text": "$7$, autant que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : il y en a toujours une de plus.\n"
            },
            {
              "text": "$6$, une de moins que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : le sens de la différence est inversé.\n"
            }
          ],
          "explanation": "Dans un arbre binaire où tout nœud interne a deux enfants, le\nnombre de feuilles dépasse de un le nombre de nœuds internes : un\nrésultat qui se prouve par récurrence sur la taille."
        },
        {
          "statement": "Dans un arbre binaire, chaque nœud interne a exactement deux\nenfants. L'arbre compte $10$ nœuds internes. Combien a-t-il de\nfeuilles ?",
          "options": [
            {
              "text": "$11$, une de plus que de nœuds internes",
              "correct": true,
              "feedback": "Bonne réponse : l'arbre réduit à une feuille vérifie la\nrelation ; remplacer une feuille par un nœud à deux enfants\najoute un interne et une feuille nette. D'où $10 + 1 = 11$.\n"
            },
            {
              "text": "$20$, deux feuilles par nœud interne",
              "correct": false,
              "feedback": "Erreur : les enfants d'un nœud interne sont souvent eux-mêmes\ninternes, pas des feuilles.\n"
            },
            {
              "text": "$10$, autant que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : il y en a toujours une de plus.\n"
            },
            {
              "text": "$9$, une de moins que de nœuds internes",
              "correct": false,
              "feedback": "Erreur : le sens de la différence est inversé.\n"
            }
          ],
          "explanation": "Dans un arbre binaire où tout nœud interne a deux enfants, le\nnombre de feuilles dépasse de un le nombre de nœuds internes : un\nrésultat qui se prouve par récurrence sur la taille."
        }
      ]
    }
  ]
}