Types et structures de données abstraites
Cours · informatique (MP2I/MPI), chapitre 6 · MP2I et MPI · le début du chapitre, la suite sur Adloun
6.1 L'algorithme et sa structure vont ensemble
Le programme ouvre sa partie « Structures de données » par une phrase qui vaut programme à elle seule : « on insiste sur le fait que le développement d'un algorithme va de pair avec la conception d'une structure de données taillée à la mesure du problème que l'on cherche à résoudre et des opérations sur les données que l'on est amené à répéter ».
L'idée est simple et elle décide de tout. Chercher un élément coûte dans un tableau non trié, dans un tableau trié, en moyenne dans une table de hachage. Ce n'est pas l'algorithme de recherche qui change : c'est la structure. Choisir sa structure, c'est déjà avoir écrit la moitié de son algorithme.
6.2 Les types du langage
6.2.1 Types prédéfinis, types composés, types paramétrés
- Prédéfini : booléen, entier, flottant, caractère. La brique de base.
- Composé : plusieurs valeurs regroupées —
structen C, enregistrement ou n-uplet en OCaml. - Paramétré : un type qui en attend un autre pour être complet. Le tableau en est l'exemple du programme :
'a arrayn'est pas un type,int arrayen est un.
Le pointeur s'ajoute en C : un type dont les valeurs sont des adresses.
« Un étudiant est capable d'inférer un type à la lecture d'un fragment de code, cependant toute théorie du typage est hors programme. » On sait donc lire une signature et deviner un type ; on n'étudie ni l'algorithme d'unification, ni les systèmes de types. De même, « la notion de classe et la programmation orientée objet sont hors programme ».
6.2.2 Mutable ou immuable
Le programme demande cette distinction, et précise qu'elle est « illustrée en langage OCaml ».
| Immuable | Mutable | |
|---|---|---|
| OCaml | 'a list, n-uplet, string | 'a array, 'a ref, champ mutable |
| Effet d'une « modification » | un nouvel objet | l'objet lui-même change |
| Partage | sans danger | tout détenteur voit le changement |
let l1 = [1; 2; 3] in
let l2 = 0 :: l1 in () (* l1 est INTACTE : l2 partage sa queue, sans copie *)
let t1 = [| 1; 2; 3 |] in
let t2 = t1 in
t2.(0) <- 99 (* t1.(0) vaut 99 AUSSI : c'est le MÊME tableau *)
La ligne let t2 = t1 ne copie rien : elle donne un second nom au même tableau. C'est instantané — et c'est pourquoi Array.copy existe. À l'inverse, 0 :: l1 ne copie rien non plus, et c'est sans danger : personne ne peut modifier l1. L'immuabilité achète le partage gratuit.
Exercices du chapitre
- Pourquoi 'a t et non t corrigé
- Trier une chaîne ne rend pas la recherche logarithmique corrigé
- Écrire un contrat avant toute réalisation corrigé
- L'invariant que seule l'abstraction protège corrigé
- Problème — Choisir d'après le profil des opérations corrigé
- Problème — Mutable ou persistant : une pile qu'on peut annuler corrigé