Aller au contenu principal

TAD et structures de données

TAD et structures de données20 min

Le contrat définit ce que vous pouvez faire. L'implémentation détermine comment ces opérations sont réalisées.

Dans cette leçon

Séparer le quoi du comment

Un type abstrait de données décrit ce que l'on peut faire avec les données et les règles que ces opérations respectent. Il ne dit pas encore où les valeurs vivent ni comment les méthodes travaillent.

Le quoi

Une pile permet d'empiler, de dépiler et de savoir si elle est vide. Elle respecte LIFO : le dernier élément ajouté ressort en premier.

Le comment

Une classe peut ranger le sommet à la fin d'un tableau ou au début d'une chaîne de nœuds. Ce choix reste invisible pour le client.
PlanQuestionExemple pour une pile
TADQuelles opérations et quelles règles ?push, pop, isEmpty; dernier entré, premier sorti.
Interface JavaQuel contrat le compilateur peut-il vérifier ?Les signatures de Pile<E>.
ImplémentationQuels objets et quelles instructions réalisent le contrat ?ArrayList en interne, sommet à la fin.
MémoireOù les valeurs et références sont-elles rangées ?Cases contiguës ou nœuds séparés.

À ne pas confondre

Un TAD n'est pas du code et ne dépend d'aucun langage : une pile existe comme concept en Java, en Python ou en JavaScript. En Java, une interface peut formaliser une partie de ce contrat, puis une classe concrète peut l'implémenter.

Exprimer le contrat en Java

Voici le contrat minimal utilisé dans le cours. Le paramètre E laisse le client choisir le type des éléments. Si ce mécanisme ne vous est pas familier, consultez l'annexe sur les types paramétrés.

Stack.java
push : ajoute au sommetpop : retire le sommetisEmpty : cas limite visible

L'interface ne contient ni ArrayList, ni Node, ni index. C'est volontaire. Un client qui utilise une pile ne devrait pas pouvoir contourner LIFO en retirant une valeur au milieu.

ArrayStack.java

Le cas vide fait partie du contrat

pop() ne peut rien retourner si la pile est vide. Cette implémentation choisit une IllegalStateException. Le comportement doit être explicite, pas découvert au hasard d'un index invalide.

Le code client type son champ avec l'interface utile. Il connaît la pile, pas les opérations supplémentaires de la classe concrète.

BrowserHistory.java

Un TAD, plusieurs rangements

Les deux représentations ci-dessous peuvent respecter exactement le même TAD. Seuls leurs gestes en mémoire diffèrent.

Sommet à la fin d'un tableau

push ajoute à droite. pop retire à droite.

Sommet au début des liens

push crée un nouveau head. pop avance head.

Ce que gagne le client

  • Une API courte qui exprime LIFO.
  • La possibilité de changer de classe concrète.

Ce que l'interface ne décide pas

  • Le coût des opérations.
  • La disposition des valeurs en mémoire.

Ce qu'il faut encore vérifier

  • Les opérations fréquentes du scénario.
  • Les cas limites de l'implémentation choisie.

Dépendre du contrat

  • • Le client n'utilise que les opérations dont il a besoin.
  • • Un remplacement d'implémentation reste local.
  • • Le compilateur vérifie les signatures.

Dépendre des détails

  • • Le client manipule directement le tableau interne.
  • • Une méthode technique fuit dans tout le programme.
  • • Changer le rangement oblige à corriger les appelants.

Choisir dans le bon ordre

Choisir d'abord une classe connue conduit souvent à tordre le besoin pour l'adapter à cette classe. Prenez les décisions dans l'autre sens.

  1. Nommez le comportement

    Avez-vous besoin d'un ordre LIFO, FIFO, d'une recherche par clé ou d'une hiérarchie ?
  2. Écrivez les opérations utiles

    Gardez le contrat aussi étroit que le besoin. Prévoyez le cas vide ou l'absence d'une valeur.
  3. Repérez les opérations dominantes

    Comptez les accès, les décalages, les copies et les liens suivis qu'elles provoqueront.
  4. Choisissez la représentation

    Prenez la classe dont les gestes internes correspondent au scénario, puis cachez-la derrière le contrat utile.

Une interface n'est pas une décoration

Ajouter une interface qui recopie toutes les méthodes d'une classe ne résout rien. Le contrat doit limiter les choix du client et exprimer le besoin. Sinon, vous avez seulement ajouté un fichier.

Vérifiez vos réflexes

Vérifiez vos réflexes

Une réponse par question. La correction apparaît tout de suite.

1. Que fixe le TAD pile ?
2. Dans « Pile<String> pile = new ArrayStack<>(); », quel type décrit le contrat vu par le client ?
3. Que pouvez-vous changer sans réécrire un client qui dépend correctement de Pile<E> ?
4. Quelle partie décide que pop retire la dernière valeur d'une ArrayList ?
5. Pourquoi un commentaire « ceci est une pile » ne suffit-il pas comme contrat Java ?

Continuez le parcours

Centre de commandes

Rechercher une page et s'y rendre