Adloun

add empile, replace écrase

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 12 — Tableaux associatifs, hachage et sérialisation

Énoncé

Qu'affiche ce fragment ? Que faudrait-il écrire pour obtenir la sémantique d'un tableau associatif ?


let h = Hashtbl.create 16 in
Hashtbl.add h "chat" 1;
Hashtbl.add h "chat" 2;
Hashtbl.add h "chat" 3;
print_int (Hashtbl.find h "chat");
Hashtbl.remove h "chat";
print_int (Hashtbl.find h "chat")

Corrigé

Mesuré : il affiche 3 puis 2.

Ce qui se passe. Hashtbl.add empile une liaison de plus sans retirer les précédentes. Après les trois appels, la table contient trois liaisons pour la clé "chat" — mesuré en les comptant avec Hashtbl.iter. find rend la dernière ajoutée, soit . Et remove n'en retire qu'une : l'avant-dernière réapparaît, d'où le .

Il faut trois remove pour que Hashtbl.mem h "chat" devienne false — mesuré.

La bonne écriture. Hashtbl.replace retire la liaison existante avant d'ajouter :


Hashtbl.replace h "chat" 1;
Hashtbl.replace h "chat" 2;
Hashtbl.replace h "chat" 3;
(* find rend 3, et il n'y a qu'UNE liaison : un seul remove suffit à l'effacer *)

Mesuré : une seule liaison, et un unique remove vide la clé.

Pourquoi le module offre les deux. Hashtbl d'OCaml n'est pas un tableau associatif mais une table à liaisons multiples — une multi-application. Elle sert quand une clé porte plusieurs valeurs, et l'empilement rend alors le rétablissement gratuit : c'est le mécanisme des portées imbriquées d'un compilateur, où l'on add en entrant dans un bloc et remove en en sortant.

Le programme tranche : l'annexe autorise Hashtbl « sans liaison multiple ». On s'en tient donc à replace, et l'on n'écrit add que sur une clé qu'on sait absente. La règle pratique tient en une phrase : si vous ne savez pas si la clé est présente, c'est replace.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.