Adloun

Corrigé Mines-Ponts 2026 Informatique II MPI — Partie 4 (Q34 à Q38) : Arbres BSP : parcours infixe, dérécursivation, génération de carte

Sujet officiel du concours Mines-Ponts, session 2026, épreuve Informatique II MPI. Corrigé rédigé par Ibrahim Alame.

Sujet officiel (PDF, site du concours)

Énoncé

Un arbre BSP (Binary Space Partitioning) partitionne récursivement l'espace ; il est rangé dans un tableau global bsp de nœuds ; les champs valent l'indice du fils, ou s'il n'existe pas. On dispose de void visite(int n), qui traite le nœud d'indice n. Le parcours infixe traite le sous-arbre « devant », puis le nœud, puis le sous-arbre « derrière ».


struct _noeud {
    int filsDevant;
    int filsDerriere;
};
typedef struct _noeud noeud;

Q34. Écrire la version récursive de void infixe(int n).
Q35. On dérécursive avec une pile explicite : un tableau d'entiers pile et un entier sommet, nombre d'éléments empilés (le sommet est en pile[sommet-1]). Compléter L1 et L2 (initialisation de la pile non précisée) pour obtenir l'ordre de visite du parcours récursif :


void infixe(int n) {
  /* pile : tableau d'indices, sommet : taille courante */

  while (true) {
    while (bsp[n].filsDevant != -1) {
      pile[sommet] = n;
      sommet++;
      n = bsp[n].filsDevant;
    }

    while (true) {
      visite(n);
      if (bsp[n].filsDerriere != -1) {
        n = bsp[n].filsDerriere;
        break;
      }

      if (sommet == 0) { return; }

      /* L1 */
      /* L2 */
    }
  }
}
Génération procédurale.

Une salle carrée est coupée récursivement en deux, dans une direction aléatoire, à une position aléatoire entre et de la dimension coupée, jusqu'à obtenir une puissance de deux de salles. Chaque nœud de l'arbre est une coupe : direction ( : verticale, : horizontale) et proportion, entier de à (en millièmes) ; les feuilles sont les salles finales. La racine coupe en , ; ses fils coupent en , et en , , etc.

Les nœuds sont numérotés à partir de (racine) dans l'ordre du parcours en largeur ; pour la figure :

0100110
370690492405580465500

Q36. rand() renvoie un entier uniforme entre et RAND_MAX, assimilé à . Écrire int alea(void), uniforme sur .
Q37. Écrire coupe* repartition(int n), qui alloue et remplit aléatoirement le tableau des n coupes d'un arbre BSP.


struct _coupe {
   int dir;        // 0 ou 1
   int proportion; // entre 300 et 700 inclus
};
typedef struct _coupe coupe;

struct _region {
    int xmin;
    int xmax;
    int ymin;
    int ymax;
};
typedef struct _region region;

Dans un repère orthonormé, la salle initiale est le carré de coins et , avec où est le nombre final de salles ; une région est décrite par son coin inférieur gauche et son coin supérieur droit .
Q38. À l'aide de repartition et d'un arbre binaire complet à n nœuds, écrire region* creation(int n), qui renvoie le tableau de toutes les régions (initiale, intermédiaires, finales) : régions pour les coupes de l'exemple.

Une salle par feuille et un couloir par séparation donnent ensuite une carte connexe :

Corrigé

Tous les programmes ont été compilés (gcc -Wall -Wextra -std=c99, sans avertissement) et exécutés : les deux parcours infixes sur arbres binaires aléatoires de à nœuds (ordres de visite identiques dans tous les cas) et sur une feuille seule ; alea sur tirages ; creation(7) sur les coupes du tableau de l'énoncé, ainsi que creation(0), creation(1) et creation(15). Aucune fuite mémoire (leaks).

Q34. Le cas de base est le sous-arbre vide, d'indice :


void infixe(int n) {
    if (n == -1) { return; }            /* sous-arbre vide */
    infixe(bsp[n].filsDevant);
    visite(n);
    infixe(bsp[n].filsDerriere);
}

Correction, par induction structurelle : sur l'arbre vide, rien n'est visité ; sur un nœud, on visite (hypothèse d'induction) les nœuds du sous-arbre « devant » dans l'ordre infixe, puis le nœud, puis ceux du sous-arbre « derrière », ce qui est la définition du parcours infixe. Terminaison : chaque appel porte sur un sous-arbre strict. Coût : un appel par nœud et un par sous-arbre vide, soit appels pour nœuds, .

Ce que le correcteur attend : le cas de base n == -1 et la visite placée entre les deux appels ; ce sont les deux lacunes relevées par le jury.

Q35. La pile contient les nœuds dont on a descendu le fils « devant » et qui restent à visiter. Quand le nœud courant n'a pas de fils « derrière », son sous-arbre est terminé : le suivant dans l'ordre infixe est le dernier nœud empilé. On le dépile :


      sommet--;              /* L1 */
      n = pile[sommet];      /* L2 */

L'ordre des deux lignes compte : le sommet de la pile est en pile[sommet-1], il faut donc décrémenter avant de lire. L'initialisation manquante (ligne 3) est int pile[TAILLE_MAX]; int sommet = 0;, avec TAILLE_MAX au moins égal à la hauteur de l'arbre : la pile ne contient que des ancêtres stricts du nœud courant. (Comme le squelette, on suppose l'arbre non vide, n .)

Correction. Notons la suite infixe du sous-arbre de racine ( vide), le fils « derrière » de , et, si la pile contient du sommet vers le fond, ce qui reste à visiter « au-dessus » du nœud courant. Deux invariants :

100 % gratuit

La suite du corrigé est sur Adloun

Le corrigé rédigé en entier, question par question, et le tuteur pour poser des questions sur ce sujet.

Voir le corrigé complet, gratuitement

Inscription gratuite en 30 secondes (e-mail, nom d'utilisateur, mot de passe, classe ou profil), sans carte bancaire : arrivée directe sur le corrigé.

Toutes les parties de l'épreuve

Corrigé complet gratuit →