<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Terminale/Arbres binaires de recherche</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Propriété d'ordre dans un arbre binaire de<br/>
recherche, opérations de recherche, d'insertion et<br/>
de suppression, complexité dans le meilleur et<br/>
dans le pire cas, équilibrage, applications aux<br/>
ensembles ordonnés dynamiques et aux dictionnaires<br/>
triés.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q01 : Propriété fondamentale</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la <strong>propriété fondamentale</strong> d'un<br/>
arbre binaire de recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les arbres binaires de recherche permettent de<br/>
maintenir un ensemble ordonné dynamique, en<br/>
offrant des opérations de recherche,<br/>
d'insertion et de suppression efficaces lorsque<br/>
l'arbre reste équilibré.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toutes les feuilles se trouvent au même niveau</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description correspond à un arbre<br/>
parfait, et non à un arbre binaire de<br/>
recherche. Un arbre binaire de recherche<br/>
se définit par une propriété d'ordre, pas<br/>
par la position de ses feuilles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Chaque nœud possède exactement deux enfants</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description correspond à un arbre<br/>
plein, qui n'a aucun rapport direct avec<br/>
l'ordre des valeurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour chaque nœud, toutes les valeurs du sous-arbre gauche sont strictement inférieures à la valeur du nœud, et toutes celles du sous-arbre droit lui sont strictement supérieures</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est la propriété d'ordre qui rend la<br/>
recherche efficace en $O(\log n)$ dans un<br/>
arbre équilibré. Cette propriété doit être<br/>
vérifiée pour <strong>chaque</strong> nœud de l'arbre, et<br/>
non uniquement pour la racine.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La racine contient la plus grande valeur de l'arbre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette propriété correspond à la définition<br/>
d'un tas (de type maximum), pas à celle<br/>
d'un arbre binaire de recherche. Dans un<br/>
arbre binaire de recherche, la racine peut<br/>
être n'importe quelle valeur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q02 : Complexité de la recherche</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans un arbre binaire de recherche <strong>équilibré</strong><br/>
contenant $n$ éléments, quelle est la complexité<br/>
de la recherche d'une valeur ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette efficacité explique pourquoi les arbres<br/>
binaires de recherche sont utilisés pour<br/>
implémenter des ensembles et dictionnaires<br/>
triés. Cette complexité dépend néanmoins<br/>
crucialement du fait que l'arbre reste<br/>
équilibré.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(n^2)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucune raison d'avoir une complexité<br/>
quadratique pour une simple recherche dans<br/>
un arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(1)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On ne peut pas accéder à un élément<br/>
quelconque en temps constant dans un arbre<br/>
binaire de recherche. La complexité dépend<br/>
au moins de la hauteur de l'arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette complexité correspond au pire cas<br/>
d'un arbre dégénéré en peigne. Pour un<br/>
arbre équilibré, on fait nettement mieux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$O(\log n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>À chaque comparaison, on élimine la moitié<br/>
des nœuds (on descend dans le sous-arbre<br/>
gauche ou dans le sous-arbre droit). Le<br/>
nombre d'étapes est donc proportionnel à<br/>
la hauteur de l'arbre, qui vaut<br/>
$O(\log n)$ lorsque l'arbre est équilibré.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q03 : Cas pire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la complexité de la recherche dans<br/>
un arbre binaire de recherche dans le <strong>pire<br/>
cas</strong>, sans contrainte d'équilibrage ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Ce phénomène de dégénérescence motive<br/>
l'utilisation d'arbres binaires de recherche<br/>
auto-équilibrés (de type AVL ou rouge-noir),<br/>
qui maintiennent une hauteur en $O(\log n)$<br/>
grâce à des opérations de rééquilibrage à<br/>
chaque insertion ou suppression.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(\sqrt{n})$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucune raison particulière n'amène à une<br/>
complexité de cette forme dans un arbre<br/>
binaire de recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(\log n)$ dans tous les cas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Sans équilibrage, l'arbre peut dégénérer.<br/>
La complexité $O(\log n)$ n'est garantie<br/>
que si l'arbre reste équilibré.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(n^2)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Même dans le pire cas, la recherche reste<br/>
en $O(n)$. La hauteur de l'arbre, qui peut<br/>
atteindre $n$, est en cause, mais la<br/>
complexité ne devient pas quadratique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$O(n)$, lorsque l'arbre a dégénéré en peigne et que chaque nœud n'a qu'un enfant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Si l'on insère par exemple les valeurs<br/>
$1, 2, 3, \ldots, n$ dans l'ordre, l'arbre<br/>
devient une liste chaînée par la droite.<br/>
La recherche y est alors en $O(n)$, comme<br/>
dans un parcours linéaire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q04 : Parcours infixe</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que donne un parcours <strong>infixe</strong> sur un arbre<br/>
binaire de recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette propriété permet de transformer un<br/>
arbre binaire de recherche en un tableau<br/>
trié en $O(n)$. C'est aussi pour cette raison<br/>
que cette structure est naturelle pour<br/>
maintenir un ensemble ordonné.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les valeurs dans un ordre aléatoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un parcours d'arbre est strictement<br/>
déterministe : il ne fait jamais appel au<br/>
hasard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les valeurs dans l'ordre croissant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est précisément la propriété remarquable<br/>
des arbres binaires de recherche. Le<br/>
parcours infixe (sous-arbre gauche, racine,<br/>
sous-arbre droit) visite naturellement les<br/>
valeurs dans l'ordre croissant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les valeurs dans l'ordre décroissant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour obtenir l'ordre décroissant, il<br/>
faudrait inverser le parcours infixe en<br/>
visitant d'abord le sous-arbre droit, puis<br/>
la racine, puis le sous-arbre gauche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune valeur particulière n'est visitée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un parcours visite chaque nœud exactement<br/>
une fois. Toutes les valeurs sont donc<br/>
parcourues.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q05 : Insertion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour insérer une valeur $v$ dans un arbre<br/>
binaire de recherche, on procède de la manière<br/>
suivante :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'insertion s'effectue en $O(h)$, où $h$ est<br/>
la hauteur de l'arbre. Lorsque l'arbre est<br/>
équilibré, on a $h = O(\log n)$. Sinon, dans<br/>
le pire cas, l'insertion peut atteindre<br/>
$O(n)$.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>On descend dans l'arbre en comparant la valeur avec chaque nœud rencontré, puis on l'insère comme nouvelle feuille à la place vide trouvée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Si la valeur $v$ est plus petite que celle<br/>
du nœud courant, on descend dans le<br/>
sous-arbre gauche ; sinon dans le<br/>
sous-arbre droit. On répète jusqu'à<br/>
rencontrer une place vide, où l'on crée<br/>
une nouvelle feuille.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On trie les valeurs, puis on la place</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'insertion est une opération locale qui<br/>
préserve l'invariant d'ordre. Aucun tri<br/>
global n'est nécessaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On la place toujours à la racine</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Insérer la nouvelle valeur à la racine<br/>
briserait la propriété d'ordre. L'insertion<br/>
doit au contraire respecter la structure<br/>
existante.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On la place dans la première feuille rencontrée, sans comparaison</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Sans comparaison avec la valeur des nœuds,<br/>
la propriété d'ordre serait violée et<br/>
l'arbre cesserait d'être un arbre binaire<br/>
de recherche.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q06 : Suppression</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La <strong>suppression</strong> d'un nœud dans un arbre<br/>
binaire de recherche est plus délicate que<br/>
l'insertion. Pourquoi ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le cas le plus délicat est celui d'un nœud à<br/>
deux enfants. Le successeur infixe se trouve<br/>
facilement : il s'agit du nœud le plus à<br/>
gauche dans le sous-arbre droit du nœud à<br/>
supprimer.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'il faut détruire l'arbre puis le reconstruire entièrement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette opération serait inutilement<br/>
coûteuse. La suppression peut se faire de<br/>
manière purement locale.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que selon que le nœud à supprimer a $0$, $1$ ou $2$ enfants, le traitement est différent, et le cas à deux enfants demande de remplacer le nœud par son successeur (ou son prédécesseur)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On distingue trois cas. Si le nœud est une<br/>
feuille, on le supprime simplement. S'il a<br/>
un seul enfant, on remplace le nœud par<br/>
cet enfant. S'il a deux enfants, on le<br/>
remplace par le <strong>successeur infixe</strong><br/>
(plus petit du sous-arbre droit) ou par le<br/>
<strong>prédécesseur infixe</strong> (plus grand du<br/>
sous-arbre gauche), puis on supprime ce<br/>
successeur (qui a au plus un enfant).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'il faut entièrement re-trier l'arbre après chaque suppression</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun tri global n'est nécessaire.<br/>
L'opération reste locale, mais doit<br/>
distinguer plusieurs cas selon la<br/>
structure du nœud supprimé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'il est impossible de supprimer un nœud dans un arbre binaire de recherche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La suppression est tout à fait possible.<br/>
Elle est simplement plus complexe que<br/>
l'insertion, en raison de la distinction<br/>
de cas.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q07 : Comparaison avec un tableau trié</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est l'<strong>avantage</strong> d'un arbre binaire de<br/>
recherche équilibré par rapport à un tableau<br/>
trié ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le compromis est clair. Si l'on a beaucoup de<br/>
recherches mais peu d'insertions, le tableau<br/>
trié peut suffire. Pour un mélange dynamique<br/>
d'opérations, l'arbre binaire de recherche<br/>
équilibré est mieux adapté.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La recherche y est plus rapide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La recherche dichotomique dans un tableau<br/>
trié est elle aussi en $O(\log n)$. Les<br/>
deux structures sont équivalentes pour la<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune différence n'existe entre les deux structures</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les deux structures se distinguent<br/>
précisément par leur comportement face<br/>
aux opérations dynamiques d'ajout et de<br/>
suppression.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'insertion et la suppression y sont en $O(\log n)$, alors qu'elles coûtent $O(n)$ dans un tableau trié, à cause du décalage des éléments</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est le principal atout d'un arbre<br/>
binaire de recherche équilibré. On peut y<br/>
maintenir un ensemble trié dynamique avec<br/>
toutes les opérations en $O(\log n)$,<br/>
alors qu'une insertion ou une suppression<br/>
au milieu d'un tableau trié coûte $O(n)$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il consomme moins de mémoire qu'un tableau</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire, un arbre binaire de<br/>
recherche consomme en général plus de<br/>
mémoire qu'un tableau, en raison des<br/>
références entre nœuds.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q08 : Construire l'arbre</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On insère successivement les valeurs $5$, $3$,<br/>
$7$, $1$, $4$ dans un arbre binaire de<br/>
recherche initialement vide. Que devient la<br/>
racine ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'ordre d'insertion détermine la forme de<br/>
l'arbre. Insérer dans l'ordre $1, 3, 4, 5, 7$<br/>
donnerait un peigne à droite (cas dégénéré).<br/>
C'est précisément pour cette raison que les<br/>
structures auto-équilibrantes sont<br/>
importantes en pratique.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$5$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La première valeur insérée devient la<br/>
racine. Toutes les insertions suivantes<br/>
deviennent des descendants de cette<br/>
racine.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$7$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La valeur $7$ est plus grande que $5$,<br/>
donc elle est insérée à droite de la<br/>
racine, mais elle ne devient pas la<br/>
racine elle-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$1$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La valeur $1$ est insérée en dernier et<br/>
finit en feuille à gauche. La racine est<br/>
toujours la <strong>première</strong> valeur insérée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$4$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La valeur $4$ est plus petite que $5$<br/>
mais plus grande que $3$. Elle finit<br/>
comme enfant droit de $3$, et n'occupe<br/>
pas la racine.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q09 : Cas d'usage</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des cas suivants est un usage typique<br/>
d'un arbre binaire de recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>En pratique, de nombreuses bibliothèques<br/>
utilisent des arbres auto-équilibrés pour<br/>
implémenter des ensembles et dictionnaires<br/>
triés. C'est le cas par exemple de <code>TreeSet</code><br/>
et <code>TreeMap</code> en Java, ou de <code>std::set</code> et<br/>
<code>std::map</code> en C++.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Maintenir dynamiquement un ensemble trié de valeurs avec des ajouts, des suppressions et des recherches fréquentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'usage emblématique. On peut par<br/>
exemple gérer une liste de scores triés<br/>
en temps réel, ou un dictionnaire dont<br/>
les clés doivent rester ordonnées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Compter le nombre de mots dans un texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un compteur simple suffit pour cette<br/>
tâche. L'utilisation d'un arbre binaire<br/>
de recherche serait disproportionnée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Afficher une image</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'affichage d'une image n'a aucun rapport<br/>
avec la structure d'arbre binaire de<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Calculer la somme des éléments d'une liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un parcours linéaire de la liste suffit.<br/>
Aucune structure ordonnée n'est<br/>
nécessaire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q10 : Recherche récursive</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle fonction Python recherche correctement<br/>
la valeur <code>v</code> dans un arbre binaire de<br/>
recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est précisément la propriété d'ordre qui<br/>
permet d'éliminer la moitié de l'arbre à<br/>
chaque comparaison. Sans cette propriété, on<br/>
retomberait sur un parcours linéaire de tous<br/>
les nœuds.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>def chercher(n, v):
    if n is None: return False
    if v == n.valeur: return True
    if v &lt; n.valeur:
        return chercher(n.gauche, v)
    return chercher(n.droit, v)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction ne descend que dans <strong>un<br/>
seul</strong> sous-arbre selon la comparaison.<br/>
C'est ce qui donne la complexité<br/>
$O(\log n)$ pour un arbre équilibré.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def chercher(n, v):
    return v == n.valeur</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction ne descend pas dans<br/>
l'arbre. Elle ne renvoie un résultat<br/>
correct que si la valeur cherchée est<br/>
exactement à la racine.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def chercher(n, v):
    return True</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction renvoie toujours <code>True</code>,<br/>
sans effectuer la moindre recherche.<br/>
Elle est manifestement incorrecte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def chercher(n, v):
    if n is None: return False
    if n.valeur == v: return True
    return chercher(n.gauche, v) or chercher(n.droit, v)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction parcourt l'arbre entier<br/>
sans exploiter la propriété d'ordre. Sa<br/>
complexité est en $O(n)$ et non en<br/>
$O(\log n)$.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q11 : Arbres AVL</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un arbre AVL est un arbre binaire de<br/>
recherche auto-équilibré. Quelle contrainte<br/>
maintient-il pour rester équilibré ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'arbre AVL garantit, pour $n$ nœuds, une<br/>
hauteur en $O(\log n)$, et donc des<br/>
opérations en $O(\log n)$. Le coût à payer<br/>
est l'effort de maintien (rotations) à<br/>
chaque insertion ou suppression.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour chaque nœud, les hauteurs des sous-arbres gauche et droit ne diffèrent jamais de plus de $1$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est la définition stricte d'un arbre<br/>
AVL. Lorsque cette propriété est violée<br/>
après une insertion, des <strong>rotations</strong><br/>
rétablissent l'équilibre. Les arbres AVL<br/>
ont été inventés par Adelson-Velsky et<br/>
Landis en $1962$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Tous les chemins de la racine aux feuilles ont la même longueur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette contrainte définirait un arbre<br/>
parfait, beaucoup plus rigide qu'un<br/>
arbre AVL.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Tous les sous-arbres doivent avoir la même taille</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La contrainte porte sur la <strong>hauteur</strong> des<br/>
sous-arbres, et non sur leur taille en<br/>
nombre de nœuds.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La racine doit toujours être la valeur médiane des valeurs présentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Maintenir la médiane à la racine après<br/>
chaque opération serait beaucoup trop<br/>
coûteux. Ce n'est pas la stratégie<br/>
adoptée par les arbres AVL.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q12 : Arbres rouge-noir</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Les arbres rouge-noir sont une autre famille<br/>
d'arbres binaires de recherche<br/>
auto-équilibrés. Quelle est leur particularité<br/>
par rapport aux arbres AVL ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les arbres rouge-noir sont à la base de<br/>
nombreuses bibliothèques standard (<code>std::map</code><br/>
en C++, <code>TreeMap</code> en Java). Ils ont été<br/>
inventés en $1972$ par Bayer, puis<br/>
généralisés par Sedgewick.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ils n'autorisent que les insertions, et pas les suppressions</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les arbres rouge-noir gèrent toutes les<br/>
opérations classiques : recherche,<br/>
insertion et suppression.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ils sont parfaitement équilibrés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ils sont en réalité moins strictement<br/>
équilibrés que les arbres AVL, mais avec<br/>
un coût d'équilibrage moindre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ils utilisent un tri par tas en interne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les arbres rouge-noir n'ont aucun rapport<br/>
avec les tas, qui constituent une<br/>
structure de données différente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Ils tolèrent un déséquilibre légèrement supérieur (la hauteur reste majorée par $2 \log n$), en échange d'opérations d'équilibrage moins fréquentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce compromis est intéressant en pratique.<br/>
Les arbres AVL sont plus rapides en<br/>
recherche, parce que plus plats, mais<br/>
plus coûteux à maintenir. Les arbres<br/>
rouge-noir équilibrent ces deux aspects.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q13 : Insertion dans le pire cas</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans un arbre binaire de recherche <strong>non<br/>
équilibré</strong>, quelle séquence d'insertions<br/>
conduit au pire cas (forme dégénérée) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour éviter ce piège, deux solutions<br/>
classiques. On peut utiliser un arbre<br/>
auto-équilibré, ou bien mélanger les<br/>
insertions au préalable. C'est aussi la<br/>
motivation des arbres randomisés (treaps),<br/>
qui maintiennent l'équilibre grâce au<br/>
hasard.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer les valeurs en commençant par la médiane</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire, insérer la médiane en<br/>
premier conduit à un arbre bien<br/>
équilibré.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer une seule valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un arbre composé d'un seul nœud ne pose<br/>
évidemment aucun problème de<br/>
dégénérescence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer les valeurs dans un ordre aléatoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Avec un ordre aléatoire, on tend vers une<br/>
bonne forme d'arbre, dont la hauteur est<br/>
en $O(\log n)$ en espérance.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Insérer les valeurs déjà triées, par ordre croissant ou décroissant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>En insérant les valeurs $1, 2, 3, \ldots, n$<br/>
dans l'ordre, chaque nouvelle valeur va à<br/>
droite de la précédente, ce qui crée un<br/>
peigne. La hauteur atteint alors $n - 1$<br/>
et toutes les opérations dégénèrent en<br/>
$O(n)$.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q14 : Application du parcours infixe</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment obtenir efficacement les valeurs<br/>
<strong>triées</strong> d'un arbre binaire de recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette propriété permet d'utiliser un arbre<br/>
binaire de recherche pour réaliser un tri.<br/>
Avec $n$ insertions en $O(n \log n)$ amortis<br/>
et un parcours infixe en $O(n)$, on obtient<br/>
un tri en $O(n \log n)$, comparable à un<br/>
tri fusion ou à un tri rapide.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier les valeurs à chaque opération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un arbre binaire de recherche maintient<br/>
déjà l'ordre par sa structure même. Il<br/>
serait redondant de retrier les valeurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ne renvoyer que les feuilles de l'arbre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On perdrait alors toutes les valeurs des<br/>
nœuds internes, ce qui est manifestement<br/>
incorrect.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Effectuer un parcours préfixe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le parcours préfixe ne donne pas les<br/>
valeurs triées en général. Seul le<br/>
parcours infixe possède cette propriété.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Effectuer un parcours infixe, qui visite naturellement les valeurs en ordre croissant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le parcours infixe en $O(n)$ donne<br/>
directement les valeurs triées. On ne<br/>
peut pas faire mieux : il faut bien<br/>
visiter chaque élément au moins une<br/>
fois.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q15 : Code d'insertion récursive</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle fonction Python insère correctement la<br/>
valeur <code>v</code> dans un arbre binaire de<br/>
recherche, en renvoyant la nouvelle racine ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette fonction est typique : elle parcourt<br/>
l'arbre depuis la racine en comparant les<br/>
valeurs, et crée un nouveau nœud à la place<br/>
vide trouvée. Sa complexité est en $O(h)$,<br/>
où $h$ est la hauteur de l'arbre.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>def inserer(n, v):
    if n is None: return Noeud(v)
    if v &lt; n.valeur:
        n.gauche = inserer(n.gauche, v)
    else:
        n.droit = inserer(n.droit, v)
    return n</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Si l'arbre est vide, la fonction crée un<br/>
nouveau nœud. Sinon, elle descend<br/>
récursivement à gauche ou à droite selon<br/>
la comparaison, puis réaffecte le<br/>
sous-arbre modifié.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def inserer(n, v):
    return Noeud(v)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction remplace l'arbre entier<br/>
par un seul nœud, perdant toutes les<br/>
valeurs précédemment insérées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def inserer(n, v):
    n.valeur = v
    return n</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction écrase la valeur de la<br/>
racine au lieu d'ajouter un nœud. Elle<br/>
ne construit pas un arbre binaire de<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def inserer(n, v):
    n.gauche = Noeud(v)
    return n</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette fonction insère toujours à gauche,<br/>
sans tenir compte de la valeur de <code>v</code>.<br/>
Elle viole donc systématiquement la<br/>
propriété d'ordre.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q16 : Construire un arbre équilibré</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour construire un arbre binaire de recherche<br/>
équilibré à partir d'un tableau trié, quelle<br/>
stratégie est la plus simple ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet algorithme est en $O(n)$. Il est utile<br/>
pour reconstruire un arbre équilibré à<br/>
partir d'une séquence triée, par exemple<br/>
lors d'une migration de données.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer les éléments dans un ordre aléatoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette approche donne un arbre presque<br/>
équilibré en moyenne, mais sans aucune<br/>
garantie absolue.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer les éléments dans l'ordre du tableau</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette stratégie produit précisément un<br/>
peigne dégénéré, puisque les valeurs<br/>
sont déjà triées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Prendre l'élément du milieu comme racine, puis construire récursivement le sous-arbre gauche à partir de la moitié inférieure et le sous-arbre droit à partir de la moitié supérieure</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'algorithme classique. La moitié<br/>
de gauche devient le sous-arbre gauche,<br/>
construit récursivement par la même<br/>
méthode, et de même pour la moitié de<br/>
droite. L'arbre obtenu est parfaitement<br/>
équilibré, de hauteur $O(\log n)$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer les éléments du dernier au premier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette stratégie produit un peigne<br/>
dégénéré dans l'autre sens, ce qui n'est<br/>
pas plus satisfaisant.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q17 : Échec de la recherche</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lorsque la recherche d'une valeur <strong>absente</strong><br/>
se termine dans un arbre binaire de recherche,<br/>
à quel endroit s'arrête-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est ce comportement qui permet la recherche<br/>
en $O(h)$ : on ne descend que dans une seule<br/>
branche, ce qui prend au plus $\log n$<br/>
étapes pour un arbre équilibré.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À la racine de l'arbre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On s'arrête en général à un endroit plus<br/>
profond dans l'arbre, lorsque la branche<br/>
recherchée est vide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction lève une exception</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On renvoie typiquement la valeur <code>False</code><br/>
ou <code>None</code>, sans lever d'exception<br/>
(sauf si on adopte volontairement cette<br/>
convention).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>À un sous-arbre vide (<code>None</code>), preuve que la valeur n'est pas présente dans l'arbre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>À chaque étape, on choisit le sous-arbre<br/>
gauche ou le sous-arbre droit. Si la<br/>
valeur n'est jamais égale au nœud<br/>
courant et que l'on atteint un<br/>
sous-arbre vide, c'est qu'elle est<br/>
absente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À une feuille, peu importe sa valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On ne s'arrête pas systématiquement à<br/>
une feuille. On peut s'arrêter à un<br/>
sous-arbre vide pendant à un nœud<br/>
interne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q18 : Vérifier la propriété d'ordre</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour vérifier qu'un arbre binaire respecte la<br/>
propriété d'arbre binaire de recherche, il<br/>
<strong>ne suffit pas</strong> de vérifier localement à<br/>
chaque nœud que :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'algorithme correct consiste à transmettre<br/>
récursivement les bornes (<code>min</code>, <code>max</code>) que<br/>
la valeur de chaque nœud doit respecter. La<br/>
racine accepte toutes les valeurs, le<br/>
sous-arbre gauche reçoit l'intervalle<br/>
$(\min, \text{valeur})$ et le sous-arbre<br/>
droit reçoit l'intervalle<br/>
$(\text{valeur}, \max)$.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les feuilles se trouvent toutes au même niveau</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucune contrainte de niveau n'est<br/>
imposée dans un arbre binaire de<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La hauteur des sous-arbres est équilibrée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette propriété correspond à<br/>
l'équilibre, et non à la propriété<br/>
d'ordre qui définit un arbre binaire de<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'enfant gauche est plus petit et l'enfant droit est plus grand. Il faut aussi vérifier que toutes les valeurs du sous-arbre gauche sont inférieures (et symétriquement pour le sous-arbre droit)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est un piège classique. Vérifier<br/>
uniquement les enfants directs ne<br/>
suffit pas. La propriété d'arbre<br/>
binaire de recherche demande que<br/>
<strong>tout</strong> le sous-arbre gauche soit<br/>
inférieur à la valeur du nœud, et pas<br/>
seulement la racine de ce sous-arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur du nœud est la moyenne de celles de ses enfants</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette propriété correspond à un autre<br/>
type d'arbre, mais elle n'a aucun<br/>
rapport avec la définition d'un arbre<br/>
binaire de recherche.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q19 : Comparaison avec une table de hachage</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comparé à une <strong>table de hachage</strong>, quel est<br/>
l'<strong>avantage</strong> d'un arbre binaire de<br/>
recherche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le choix dépend du besoin. Pour des accès<br/>
par clé sans contrainte d'ordre, la table<br/>
de hachage est préférable. Pour maintenir<br/>
les valeurs en ordre ou répondre à des<br/>
requêtes par intervalle, l'arbre binaire de<br/>
recherche est mieux adapté.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il maintient les éléments dans l'ordre, ce qui permet de répondre à des requêtes par intervalle ou de retrouver le voisin le plus proche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un arbre binaire de recherche permet de<br/>
répondre à des questions comme « tous<br/>
les éléments entre $a$ et $b$ » ou<br/>
« le plus petit élément supérieur ou égal<br/>
à $v$ » en $O(\log n)$. Une table de<br/>
hachage ne le permet pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il consomme moins de mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation n'est pas<br/>
systématiquement vraie. La consommation<br/>
mémoire dépend de l'implémentation des<br/>
deux structures.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il est plus simple à implémenter</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire, un arbre binaire de<br/>
recherche auto-équilibré est en<br/>
général plus complexe à implémenter<br/>
qu'une table de hachage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La recherche y est plus rapide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'inverse. Une table de hachage<br/>
a une recherche en $O(1)$ amorti, ce<br/>
qui est plus rapide que le $O(\log n)$<br/>
d'un arbre binaire de recherche.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q20 : Lecture d'un arbre</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On insère successivement les valeurs $5$,<br/>
$2$, $8$, $1$, $3$ dans un arbre binaire de<br/>
recherche initialement vide. Quel est le<br/>
résultat de son parcours infixe ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet exemple illustre parfaitement la<br/>
propriété d'ordre. Dessiner l'arbre est<br/>
souvent utile pour visualiser et vérifier<br/>
les différents parcours.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$8, 5, 3, 2, 1$ (ordre décroissant)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette séquence correspond au parcours<br/>
infixe inversé, et non au parcours<br/>
infixe standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$1, 2, 3, 5, 8$ (ordre croissant)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le parcours infixe donne toujours les<br/>
valeurs en ordre croissant. On peut le<br/>
vérifier en construisant l'arbre :<br/>
racine $5$, sous-arbre gauche enraciné<br/>
en $2$ (avec $1$ et $3$), sous-arbre<br/>
droit réduit à $8$. Le parcours infixe<br/>
donne bien $1, 2, 3, 5, 8$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$5, 2, 1, 3, 8$ (parcours préfixe)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette séquence correspond au parcours<br/>
<strong>préfixe</strong> (racine, gauche, droite),<br/>
et non au parcours infixe.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$5, 2, 8, 1, 3$ (ordre d'insertion)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le parcours infixe d'un arbre binaire<br/>
de recherche donne les valeurs triées,<br/>
et non l'ordre d'insertion d'origine.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q21 : Suppression d'un nœud à deux enfants</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour supprimer un nœud à <strong>deux enfants</strong> dans<br/>
un arbre binaire de recherche, par quoi le<br/>
remplace-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le successeur infixe se trouve en<br/>
descendant une fois à droite, puis tout à<br/>
gauche. Cette opération s'effectue en<br/>
$O(h)$ étapes au pire, où $h$ est la<br/>
hauteur de l'arbre.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Par le sous-arbre gauche complet</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Déplacer un sous-arbre entier ne<br/>
conserverait pas la propriété d'ordre<br/>
de l'arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Par la racine de l'arbre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette opération briserait toute la<br/>
structure de l'arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Par une feuille choisie au hasard</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Choisir une feuille au hasard violerait<br/>
la propriété d'ordre de l'arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Par son successeur infixe (le plus petit nœud du sous-arbre droit) ou par son prédécesseur infixe (le plus grand du sous-arbre gauche)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce nœud est le plus proche du nœud<br/>
supprimé dans l'ordre des valeurs. Il a<br/>
forcément au plus un enfant (sinon, un<br/>
nœud encore plus à gauche existerait),<br/>
ce qui rend sa suppression simple. On<br/>
copie sa valeur dans le nœud à<br/>
supprimer, puis on supprime ce<br/>
successeur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q22 : Hauteur attendue</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour un arbre binaire de recherche construit<br/>
en insérant $n$ valeurs <strong>dans un ordre<br/>
aléatoire</strong>, quelle est la hauteur attendue ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Ce résultat justifie l'utilisation<br/>
d'arbres binaires de recherche non<br/>
auto-équilibrés lorsque l'on contrôle<br/>
l'ordre d'insertion (par exemple en<br/>
mélangeant les données au préalable). Les<br/>
structures auto-équilibrées garantissent<br/>
une complexité en $O(\log n)$ même dans<br/>
le pire cas.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$\Theta(\sqrt{n})$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette croissance ne correspond pas au<br/>
comportement asymptotique de la<br/>
hauteur d'un arbre binaire de<br/>
recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$\Theta(n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette hauteur correspond au pire cas<br/>
(insertion dans un ordre déjà trié) et<br/>
non au cas moyen. Avec un ordre<br/>
aléatoire, le résultat est bien<br/>
meilleur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$\Theta(\log n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est un résultat classique. En<br/>
espérance (sur l'ordre aléatoire<br/>
d'insertion), la hauteur est en<br/>
$\Theta(\log n)$. Toutes les opérations<br/>
ont alors une complexité moyenne en<br/>
$O(\log n)$, sans qu'aucun équilibrage<br/>
explicite soit nécessaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$\Theta(1)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La hauteur d'un arbre croît<br/>
nécessairement avec le nombre de<br/>
valeurs $n$. Elle ne peut pas rester<br/>
constante.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q23 : Tri par arbre binaire de recherche</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le tri par arbre binaire de recherche, qui<br/>
consiste à insérer $n$ valeurs dans un arbre<br/>
puis à effectuer un parcours infixe, a une<br/>
complexité de :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet algorithme illustre un compromis : il<br/>
est avantageux pour des données aléatoires,<br/>
mais fragile dans le pire cas. C'est<br/>
pourquoi on préfère en pratique le tri<br/>
fusion (toujours en $O(n \log n)$<br/>
garanti) ou le tri rapide (souvent en<br/>
$O(n \log n)$ avec un bon choix de<br/>
pivot).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(n!)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette complexité factorielle est<br/>
encore plus excessive et ne correspond<br/>
à aucun algorithme de tri raisonnable.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>$O(n \log n)$ en moyenne (avec un ordre aléatoire), mais $O(n^2)$ dans le pire cas (ordre déjà trié)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Chaque insertion est en $O(\log n)$ en<br/>
moyenne, ce qui donne $O(n \log n)$<br/>
pour les $n$ insertions, auxquelles<br/>
s'ajoute $O(n)$ pour le parcours<br/>
infixe. Total : $O(n \log n)$ en<br/>
moyenne. Mais avec un ordre<br/>
d'insertion défavorable, la hauteur<br/>
explose et la complexité atteint<br/>
$O(n^2)$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Insérer $n$ valeurs dans une structure<br/>
ordonnée ne peut pas se faire en<br/>
$O(n)$. Tout tri par comparaisons est<br/>
au moins en $\Omega(n \log n)$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$O(2^n)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette complexité exponentielle n'a<br/>
aucune raison d'apparaître dans un<br/>
tri.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q24 : Successeur d'un nœud</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Étant donné un nœud $n$ dans un arbre binaire<br/>
de recherche, comment trouver son<br/>
<strong>successeur infixe</strong>, c'est-à-dire la valeur<br/>
immédiatement supérieure ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette logique permet d'implémenter un<br/>
<strong>itérateur</strong> sur un arbre binaire de<br/>
recherche, qui produit les valeurs en<br/>
ordre croissant sans stockage<br/>
supplémentaire (à part une pile implicite<br/>
pour remonter dans l'arbre).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La racine de l'arbre est toujours le successeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description est trop simpliste<br/>
et incorrecte. Le successeur d'un<br/>
nœud n'est pas en général la racine.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En descendant toujours à gauche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette stratégie n'est pas systématique.<br/>
Le successeur peut très bien se trouver<br/>
ailleurs dans l'arbre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le successeur est choisi au hasard parmi les autres nœuds</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La détermination du successeur est<br/>
strictement déterministe : aucun<br/>
hasard n'intervient.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Si le nœud $n$ a un sous-arbre droit, son successeur est le nœud le plus à gauche de ce sous-arbre. Sinon, c'est le premier ancêtre dont $n$ se trouve dans le sous-arbre gauche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est la définition correcte. En<br/>
parcourant ainsi, on visite l'arbre<br/>
dans l'ordre infixe sans utiliser la<br/>
récursion, ce qui est très pratique<br/>
pour implémenter un itérateur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q25 : Quand utiliser un arbre binaire de recherche ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des cas suivants justifie l'usage<br/>
d'un arbre binaire de recherche<br/>
auto-équilibré plutôt qu'une autre structure<br/>
?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour résumer : on utilise un arbre binaire<br/>
de recherche pour des accès <strong>dynamiques</strong><br/>
avec maintien d'un <strong>ordre</strong> sur les<br/>
valeurs. Pour des données statiques ou<br/>
sans besoin d'ordre, des structures plus<br/>
simples suffisent.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Implémenter un dictionnaire dont les clés sont triées dynamiquement, avec des recherches par intervalle fréquentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est exactement le cas d'usage des<br/>
arbres binaires de recherche<br/>
auto-équilibrés. Cette structure<br/>
permet, en $O(\log n)$, de répondre à<br/>
des requêtes comme « les clés entre<br/>
$a$ et $b$ » ou « la plus petite clé<br/>
supérieure ou égale à $v$ ».</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Calculer la somme des éléments d'une grande liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un parcours linéaire en $O(n)$ suffit<br/>
pour cette tâche. Aucune structure<br/>
d'arbre n'apporterait de gain.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Stocker une liste fixe de noms à afficher</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour des données statiques, une liste<br/>
triée stockée dans un tableau suffit.<br/>
Aucun arbre binaire de recherche<br/>
n'est nécessaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier $1\,000$ entiers une seule fois</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour ce besoin, les algorithmes de tri<br/>
classiques (tri fusion, tri rapide)<br/>
sont plus simples et tout aussi<br/>
efficaces.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q26 : Trace d'insertions successives</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On part d'un arbre binaire de recherche<br/>
vide. On y insère successivement les valeurs<br/>
$10, 5, 15, 3, 7, 12$. À quoi ressemble la<br/>
structure obtenue ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet arbre obtenu ($6$ nœuds, hauteur $2$) est<br/>
bien équilibré, ce qui n'est pas un hasard :<br/>
la séquence d'insertion alterne intelligemment<br/>
entre les côtés. Avec une mauvaise séquence<br/>
($1, 2, 3, 4, 5, 6$), on aurait obtenu un<br/>
peigne de hauteur $5$.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Tous les nœuds sont des feuilles d'une<br/>
racine vide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un arbre binaire de recherche<br/>
n'a pas de « racine vide ». La première<br/>
valeur insérée devient la racine, et les<br/>
suivantes sont placées comme descendants.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Tous les nœuds sur une branche droite,<br/>
formant un peigne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on aurait un peigne uniquement<br/>
si les valeurs étaient insérées dans<br/>
l'ordre croissant ou décroissant. Ici,<br/>
l'ordre est plus équilibré.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Racine $5$ ; tous les autres nœuds<br/>
répartis selon leur valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la racine est toujours la<br/>
<strong>première</strong> valeur insérée, ici $10$,<br/>
pas $5$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Racine $10$ ; sous-arbre gauche : $5$ avec<br/>
$3$ à gauche et $7$ à droite ; sous-arbre<br/>
droit : $15$ avec $12$ à gauche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque insertion, on<br/>
compare avec la racine pour choisir le<br/>
sous-arbre. $10$ devient racine. $5 &lt; 10$<br/>
va à gauche. $15 &gt; 10$ va à droite. $3 &lt; 10$<br/>
puis $3 &lt; 5$ va à gauche de $5$. $7 &lt; 10$<br/>
puis $7 &gt; 5$ va à droite de $5$. $12 &gt; 10$<br/>
puis $12 &lt; 15$ va à gauche de $15$.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q27 : Code de vérification de la propriété</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle fonction Python vérifie correctement<br/>
qu'un arbre binaire respecte la propriété<br/>
d'arbre binaire de recherche (en utilisant<br/>
des bornes minimum et maximum) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le piège pédagogique de cette question est<br/>
la première option, qui semble naturelle<br/>
mais rate les violations à distance. C'est<br/>
pour cela que la transmission de bornes par<br/>
paramètre est essentielle : elle propage la<br/>
contrainte d'ordre tout au long de la<br/>
descente récursive.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def est_abr(n):
    if n is None:
        return True
    if n.gauche and n.gauche.valeur &gt;= n.valeur:
        return False
    if n.droit and n.droit.valeur &lt;= n.valeur:
        return False
    return est_abr(n.gauche) and est_abr(n.droit)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur classique : on ne vérifie que la<br/>
relation parent/enfant direct. Cela rate<br/>
des cas comme racine $10$, gauche $5$,<br/>
droite-gauche-droite $20$ (qui est dans<br/>
le sous-arbre gauche de $10$ mais<br/>
supérieure à $10$). L'arbre serait<br/>
déclaré valide à tort.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def est_abr(n):
    return n is None</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette fonction renvoie <code>True</code><br/>
uniquement pour l'arbre vide, et <code>False</code><br/>
pour tout arbre non vide, ce qui est<br/>
manifestement faux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>def est_abr(n, mini=float('-inf'), maxi=float('inf')):
    if n is None:
        return True
    if not (mini &lt; n.valeur &lt; maxi):
        return False
    return est_abr(n.gauche, mini, n.valeur) and est_abr(n.droit, n.valeur, maxi)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on transmet à chaque<br/>
appel récursif les bornes que la valeur<br/>
du sous-arbre doit respecter. À gauche,<br/>
on resserre la borne supérieure ; à<br/>
droite, la borne inférieure. C'est le<br/>
schéma correct qui détecte aussi les<br/>
violations « profondes » (par exemple,<br/>
un nœud lointain qui violerait l'ordre).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def est_abr(n):
    if n is None:
        return True
    return parcours_infixe(n) == sorted(parcours_infixe(n))</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette approche est correcte mais<br/>
inefficace : elle nécessite un parcours<br/>
complet, un tri en $O(n \log n)$ et une<br/>
comparaison. La version récursive avec<br/>
bornes est en $O(n)$ et plus élégante.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Arbres binaires de recherche — Q28 : Minimum et maximum dans un ABR</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment trouver respectivement le <strong>minimum</strong><br/>
et le <strong>maximum</strong> d'un arbre binaire de<br/>
recherche non vide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette propriété est exploitée dans la<br/>
suppression d'un nœud à deux enfants : on<br/>
remplace le nœud par son <strong>successeur<br/>
infixe</strong> (le minimum de son sous-arbre droit)<br/>
ou son <strong>prédécesseur infixe</strong> (le maximum de<br/>
son sous-arbre gauche), tous deux trouvables<br/>
en $O(h)$.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le minimum est toujours la racine, le<br/>
maximum est toujours une feuille</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la racine est la <strong>première<br/>
valeur insérée</strong>, pas le minimum. Le<br/>
minimum est dans le sous-arbre le plus à<br/>
gauche. Quant au maximum, il peut être<br/>
n'importe où à droite, pas forcément une<br/>
feuille.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On parcourt tout l'arbre et on retient les<br/>
valeurs minimale et maximale au fur et à<br/>
mesure</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette méthode fonctionne (en $O(n)$) mais<br/>
ignore la propriété d'ordre. Avec<br/>
l'arbre binaire de recherche, on peut<br/>
faire bien mieux en descendant<br/>
directement à gauche ou à droite, en<br/>
$O(h)$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le minimum se trouve en descendant toujours<br/>
à gauche depuis la racine ; le maximum<br/>
en descendant toujours à droite. Les<br/>
deux opérations sont en $O(h)$ où $h$ est<br/>
la hauteur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par la propriété d'ordre,<br/>
tous les nœuds plus petits qu'un nœud<br/>
donné sont à sa gauche. En descendant<br/>
systématiquement à gauche jusqu'à<br/>
atteindre une feuille (sans enfant<br/>
gauche), on trouve la plus petite valeur.<br/>
Symétriquement à droite pour le maximum.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le minimum et le maximum sont les deux<br/>
enfants de la racine</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : seul l'enfant gauche <strong>direct</strong><br/>
de la racine peut être plus petit qu'elle,<br/>
pas un éventuel descendant plus profond.<br/>
Et symétriquement à droite. La descente<br/>
jusqu'au bout est nécessaire.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
