EuraStudy
Fiches/NSI — Numérique et sciences informatiques/Structures de données linéaires
Fiches · NSI — Numérique et sciences informatiquesFR · Bac

Structures de données linéaires

Listes, piles, files et dictionnaires forment la boîte à outils du programmeur pour organiser des données. Cette fiche distingue rigoureusement l'interface d'une structure (le contrat des opérations) de son implémentation (sa représentation interne en Python), puis spécifie et implémente piles (LIFO), files (FIFO) et dictionnaires, et apprend à choisir la structure adaptée à un problème en justifiant le choix par le coût des opérations.

5 sections·~19 min de lecture·4 compétences·Niveau Base 1 · Standard 3 · Approfondissement 1·Vérifié · 06/2026

T·0222 / 10
Profil d’examen
C1 · Distinguer la notion d'interface (spécification des opérations et de leur contrat) de celle d'implémentation (représentation interne) d'une structure de données.C2 · Spécifier puis implémenter en Python une structure de données linéaire : liste, pile (empiler, dépiler, est_vide, sommet) et file (enfiler, défiler, est_vide).C3 · Utiliser un dictionnaire : associer une clé à une valeur, accéder par clé, parcourir l'ensemble des couples clé-valeur.C4 · Choisir une structure de données adaptée à la situation à modéliser et justifier ce choix par le coût des opérations.
Opérateurs :spécifierimplémenterdistinguerchoisirjustifiertraceranalyserinterpréter
Profondeur

Profondeur de lecture : Approfondi

Texte

Taille du texte : Standard

Sommaire · 5 sections▾
  1. Structures de données linéaires
    • 01Type abstrait : interface contre implémentation○
    • 02Listes : tableaux dynamiques et listes chaînées◐
    • 03Piles (LIFO) et files (FIFO) : opérations et applications◐
    • 04Dictionnaires : clé, valeur et table de hachage◐
    • 05Choisir et implémenter la structure adaptée à un problème●
§ 01

Type abstrait : interface contre implémentation#

●○○BaseLPeduscol-programme-nsi-terminale

Type abstrait « Pile » : une interface, plusieurs implémentations

Une interface, plusieurs implémentationsGraphe, Pile (interface) → liste Python (append/pop), Pile (interface) → liste chaînée, Pile (interface) → tableau de taille fixePile (interface)liste Python(append/pop)liste chaînéetableau detaille fixe
Fig. 1Une même interface (le contrat : empiler, dépiler, sommet, est_vide) admet plusieurs implémentations. L'interface dit CE QUE fait la structure ; l'implémentation, COMMENT elle le fait.

Points clés

Un type abstrait de données (TAD) décrit un ensemble de valeurs et les opérations autorisées sur elles, sans préciser comment ces valeurs sont stockées en mémoire. C'est un contrat.
L'interface répond à la question « CE QUE fait la structure » : la liste des opérations, leur signature (entrées/sorties) et leur contrat (préconditions, effet). Exemple pour une pile : empiler(p, x), dépiler(p), sommet(p), est_vide(p).
L'implémentation répond à la question « COMMENT elle le fait » : la représentation interne choisie (un tableau dynamique, une liste chaînée de maillons, etc.) et le code des opérations sur cette représentation.
Un même type abstrait admet plusieurs implémentations qui respectent toutes le même contrat ; on peut donc changer l'implémentation sans modifier le code qui utilise la structure. C'est le principe d'abstraction (ou d'encapsulation).
Une structure peut être implémentée à l'aide d'une autre : une pile ou une file au moyen d'une liste, un dictionnaire au moyen d'une liste de couples (clé, valeur). On parle d'implémentation par délégation.
Exemple corrigé

Spécifier l'interface d'une pile, indépendamment de l'implémentation

Rédigez l'interface (le contrat) d'une pile d'entiers : pour chaque opération, donnez sa signature, son effet et, le cas échéant, sa précondition. N'écrivez aucun code de représentation interne.

  1. 01creer_pile()

    Signature : creer_pile() → Pile. Effet : renvoie une nouvelle pile vide. Précondition : aucune.

  2. 02est_vide(p)

    Signature : est_vide(p) → bool. Effet : renvoie True si la pile p ne contient aucun élément, False sinon. Précondition : aucune.

  3. 03empiler(p, x)

    Signature : empiler(p, x) → None. Effet : ajoute x au sommet de p ; après l'appel, sommet(p) vaut x. Précondition : aucune.

  4. 04depiler(p)

    Signature : depiler(p) → élément. Effet : retire et renvoie l'élément situé au sommet de p. Précondition : p ne doit pas être vide (sinon l'opération est indéfinie).

  5. 05sommet(p)

    Signature : sommet(p) → élément. Effet : renvoie l'élément au sommet SANS le retirer. Précondition : p ne doit pas être vide.

Résultat : L'interface décrit entièrement le comportement attendu de la pile (le contrat) sans rien dire de sa représentation : on peut maintenant l'implémenter de plusieurs façons.

Objectif Bac

  • Objectif Bac : énoncer la différence interface / implémentation et l'illustrer sur un exemple (deux représentations possibles d'une même pile).
  • Objectif Bac : à partir d'une interface donnée, écrire le code d'une opération en respectant exactement sa signature et son contrat (sans changer les noms ni les paramètres imposés).

Erreurs fréquentes

  • Confondre l'interface et l'implémentation : décrire la structure par sa représentation interne (« une pile, c'est un tableau ») au lieu de son contrat d'opérations.
  • Croire qu'il existe une seule « bonne » implémentation : tant que le contrat est respecté, plusieurs représentations sont valides ; elles diffèrent seulement par leurs coûts.

Révision active

On donne l'interface d'une file : creer_file(), enfiler(f, x), defiler(f), est_vide(f). Sans choisir d'implémentation, écrivez en français le contrat (effet attendu, valeur renvoyée, précondition) de chacune des quatre opérations.

Rappel actif

Rappelle-toi les points clés — puis révèle.

Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques (voie générale) — programmes et ressources (Éduscol — Ministère de l'Éducation nationale)

§ 02

Listes : tableaux dynamiques et listes chaînées#

●●○StandardLPeduscol-programme-nsi-terminale

Liste chaînée : maillons valeur / suivant et coûts des opérations

Liste chaînée : maillons valeur / suivantGraphe, 12 → 5, 5 → 9, 9 → None1259Nonesuivantsuivantsuivant
Fig. 2Chaque maillon porte une valeur et une référence vers le suivant ; le dernier pointe vers None. Insérer en tête est en O(1) (on crée un maillon sans rien décaler) ; accéder à l'élément d'indice i coûte O(i) (suivre i références).

Points clés

Une liste est une suite ordonnée d'éléments accessibles par leur position (indice). Les opérations usuelles sont l'accès à l'élément d'indice i, l'insertion et la suppression d'un élément.
Le type list de Python est un tableau dynamique : les éléments sont rangés dans une zone contiguë de mémoire qui s'agrandit automatiquement. L'accès par indice tab[i] est en temps constant O(1) ; ajouter en fin (append) est en O(1) amorti.
En revanche, insérer ou supprimer en début ou au milieu d'un tableau dynamique oblige à décaler tous les éléments suivants : c'est en O(n) dans le pire des cas.
Une liste chaînée représente la suite par une chaîne de maillons : chaque maillon contient une valeur et une référence vers le maillon suivant (None pour le dernier). On accède à la liste par sa tête.
Dans une liste chaînée, insérer ou supprimer en tête se fait en O(1) (on ne déplace rien, on rebranche une référence) ; mais l'accès à l'élément d'indice i coûte O(i) car il faut parcourir les maillons un à un.
Choisir entre tableau dynamique et liste chaînée dépend des opérations dominantes : accès fréquent par indice → tableau ; insertions/suppressions fréquentes en tête → liste chaînée.
acceˋs tab[i]:O(1)insertion en teˆte (tableau):O(n)\text{accès tab}[i] : \mathcal{O}(1) \qquad \text{insertion en tête (tableau)} : \mathcal{O}(n)acceˋs tab[i]:O(1)insertion en teˆte (tableau):O(n)

Coûts dans un tableau dynamique (list Python)

L'accès direct par indice est immédiat, mais insérer en tête décale les n éléments suivants.

acceˋs aˋ l’indice i (chaıˆneˊe):O(i)insertion en teˆte:O(1)\text{accès à l'indice } i \text{ (chaînée)} : \mathcal{O}(i) \qquad \text{insertion en tête} : \mathcal{O}(1)acceˋs aˋ l’indice i (chaıˆneˊe):O(i)insertion en teˆte:O(1)

Coûts dans une liste chaînée

Le compromis est inversé : l'accès devient linéaire, mais l'insertion en tête est immédiate car on ne déplace aucun élément.

Exemple corrigé

Insertion en tête d'une liste chaînée

On modélise une liste chaînée par une classe Maillon (attributs valeur et suivant). Écrivez la fonction inserer_en_tete(tete, x) qui insère x au début et renvoie la nouvelle tête, et justifiez son coût.

  1. 01Représentation

    Un maillon a deux champs : valeur (l'entier stocké) et suivant (le maillon d'après, ou None). La liste est désignée par son premier maillon, la tête.

  2. 02Créer le nouveau maillon

    On crée m = Maillon(x). On veut que m précède l'ancienne tête : on règle donc m.suivant sur l'ancienne tête.

  3. 03Renvoyer la nouvelle tête

    Le nouveau premier maillon est m : on le renvoie. Aucun autre maillon n'a été déplacé ni modifié.

  4. 04Coût

    On a effectué un nombre constant d'opérations (création d'un maillon + une affectation), indépendant de la longueur de la liste.

Résultat : inserer_en_tete s'écrit en trois lignes (m = Maillon(x) ; m.suivant = tete ; return m) et s'exécute en temps constant O(1), là où l'insertion en tête d'un tableau dynamique serait en O(n).

Objectif Bac

  • Objectif Bac : comparer les coûts (accès, insertion en tête, insertion en fin) d'un tableau dynamique et d'une liste chaînée, et justifier le choix selon le problème.
  • Objectif Bac : implémenter une liste chaînée simple (maillon valeur/suivant) et écrire une opération de parcours, d'insertion en tête ou de recherche.

Erreurs fréquentes

  • Croire que l'accès tab[i] dans une liste chaînée est en O(1) comme dans un tableau : il faut suivre i références, donc O(i).
  • Oublier de traiter le maillon de fin de chaîne (référence None) dans un parcours, ce qui provoque une boucle infinie ou une erreur d'attribut sur None.

Révision active

Implémentez une liste chaînée d'entiers (classe Maillon avec attributs valeur et suivant). Écrivez une fonction longueur(tete) qui renvoie le nombre de maillons, et une fonction inserer_en_tete(tete, x) qui renvoie la nouvelle tête après insertion de x.

Rappel actif

Rappelle-toi les points clés — puis révèle.

Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques (voie générale) — programmes et ressources (Éduscol — Ministère de l'Éducation nationale)

§ 03

Piles (LIFO) et files (FIFO) : opérations et applications#

●●○StandardLPeduscol-programme-nsi-terminale

Pile (LIFO) : empiler et dépiler au sommet

Pile (LIFO) : empiler et dépiler au sommetTableau de 3 colonnes et 6 lignes, Données: Opération · Pile (fond → sommet) · Renvoie; empiler(3) · [3] · —; empiler(7) · [3, 7] · —; empiler(8) · [3, 7, 8] · —; sommet() · [3, 7, 8] · 8; dépiler() · [3, 7] · 8; dépiler() · [3] · 7, cellule mise en évidence : 8OPÉRATIONPILE (FOND → SOMMET)RENVOIEempiler(3)[3]—empiler(7)[3, 7]—empiler(8)[3, 7, 8]—sommet()[3, 7, 8]8dépiler()[3, 7]8dépiler()[3]7
Fig. 3On empile et on dépile au même bout, le sommet. Le premier dépiler renvoie 8, le dernier entré (cellule mise en évidence) : c'est la discipline LIFO (dernier entré, premier sorti).

Points clés

Une pile est une structure LIFO (last in, first out) : le dernier élément entré est le premier sorti. Toutes les opérations se font au même bout, le sommet : empiler ajoute au sommet, dépiler retire le sommet.
Opérations d'une pile : empiler(x), dépiler() (retire et renvoie le sommet), sommet() (lit le sommet sans le retirer), est_vide(). Dépiler ou lire le sommet d'une pile vide est une erreur (précondition : pile non vide).
Une file est une structure FIFO (first in, first out) : le premier élément entré est le premier sorti. Les deux bouts sont distincts : enfiler ajoute en queue, défiler retire en tête. L'ordre d'arrivée est préservé.
Opérations d'une file : enfiler(x), défiler() (retire et renvoie la tête), est_vide(). Comme pour la pile, défiler une file vide est indéfini.
Implémentation en Python : une liste sert naturellement de pile via append (empiler) et pop (dépiler) qui agissent en fin de liste en O(1) amorti. Pour une file, retirer en tête avec pop(0) est en O(n) ; on préfère collections.deque, dont les retraits aux deux bouts sont en O(1).
Applications typiques : la pile sert à l'évaluation d'expressions, à la vérification du bon parenthésage et à la gestion des appels de fonctions (pile d'exécution) ; la file sert à la gestion de tampons (files d'attente) et au parcours en largeur d'un graphe.
Pile (LIFO):empiler puis deˊpiler renvoie le DERNIER entreˊ\text{Pile (LIFO)} : \text{empiler puis dépiler renvoie le DERNIER entré}Pile (LIFO):empiler puis deˊpiler renvoie le DERNIER entreˊ

Discipline LIFO de la pile

Last In, First Out : la dernière valeur empilée est la première dépilée.

File (FIFO):enfiler puis deˊfiler renvoie le PREMIER entreˊ\text{File (FIFO)} : \text{enfiler puis défiler renvoie le PREMIER entré}File (FIFO):enfiler puis deˊfiler renvoie le PREMIER entreˊ

Discipline FIFO de la file

First In, First Out : la file préserve l'ordre d'arrivée des éléments.

File (FIFO) : enfiler en queue, défiler en tête

File (FIFO) : enfiler en queue, défiler en têteTableau de 3 colonnes et 5 lignes, Données: Opération · File (tête → queue) · Renvoie; enfiler(3) · [3] · —; enfiler(7) · [3, 7] · —; enfiler(8) · [3, 7, 8] · —; défiler() · [7, 8] · 3; défiler() · [8] · 7, cellule mise en évidence : 3OPÉRATIONFILE (TÊTE → QUEUE)RENVOIEenfiler(3)[3]—enfiler(7)[3, 7]—enfiler(8)[3, 7, 8]—défiler()[7, 8]3défiler()[8]7
Fig. 4On enfile en queue, on défile en tête. Le premier défiler renvoie 3, le premier entré (cellule mise en évidence) : c'est la discipline FIFO (premier entré, premier sorti) ; l'ordre d'arrivée est préservé.

Application : une pile vérifie le bon parenthésage de « ([]) »

Une pile vérifie le bon parenthésage de ([])Tableau de 3 colonnes et 4 lignes, Données: Caractère lu · Action · Pile (fond → sommet); ( · empiler ( · (; [ · empiler [ · ( [; ] · dépiler [ (paire OK) · (; ) · dépiler ( (paire OK) · vide, cellule mise en évidence : videCARACTÈRE LUACTIONPILE (FOND → SOMMET)(empiler (([empiler [( []dépiler [ (paire OK)()dépiler ( (paire OK)vide
Fig. 5On empile chaque parenthèse ouvrante et on dépile à chaque fermante (en vérifiant qu'elle correspond au sommet). Une pile vide à la fin (cellule mise en évidence) signe une expression bien parenthésée.
Exemple corrigé

Dérouler une suite d'opérations sur une pile puis sur une file

On part d'une structure vide et on exécute la suite d'opérations : ajouter 3, ajouter 7, ajouter 8, puis retirer, retirer. Donnez la valeur renvoyée par chaque retrait et l'état final (a) si la structure est une pile, (b) si c'est une file.

  1. 01Pile — empilements

    On empile 3, 7, 8 dans cet ordre. De bas en haut, la pile contient [3, 7, 8] ; le sommet est 8.

  2. 02Pile — dépilements

    Le premier depiler() retire le sommet 8 et le renvoie. Le second retire le nouveau sommet 7 et le renvoie (LIFO). Il reste [3].

  3. 03File — enfilements

    On enfile 3, 7, 8 ; de la tête vers la queue : [3, 7, 8]. La tête est 3.

  4. 04File — défilements

    Le premier defiler() retire la tête 3 et le renvoie. Le second retire la nouvelle tête 7 et le renvoie (FIFO). Il reste [8].

Résultat : Pile : les retraits renvoient 8 puis 7, état final [3]. File : les retraits renvoient 3 puis 7, état final [8]. Même suite d'entrées, ordres de sortie opposés : c'est toute la différence LIFO / FIFO.

Exemple corrigé

Vérifier le bon parenthésage avec une pile

À l'aide d'une pile, écrivez l'algorithme bien_parenthesee(ch) qui renvoie True si la chaîne ch, composée des symboles ( ) [ ], est correctement parenthésée (chaque fermante correspond à la dernière ouvrante non encore fermée). Déroulez-le sur « ([]) » puis sur « ([)] ».

  1. 01Principe

    On parcourt ch de gauche à droite. À chaque ouvrante ( ou [, on l'empile. À chaque fermante, on dépile : la pile doit être non vide et son sommet doit être l'ouvrante correspondante, sinon la chaîne est mal parenthésée.

  2. 02Test final

    Après lecture complète, la chaîne est bien parenthésée si et seulement si la pile est vide (toutes les ouvrantes ont été refermées).

  3. 03Dérouler « ([]) »

    ( → empile ( ; [ → empile [ ; ] → sommet [ correspond, on dépile ; ) → sommet ( correspond, on dépile. Pile vide à la fin → True.

  4. 04Dérouler « ([)] »

    ( → empile ( ; [ → empile [ ; ) → sommet est [ mais on attend [ ↔ ], incompatibilité → False (les paires se croisent).

Résultat : L'algorithme renvoie True pour « ([]) » (pile vide à la fin) et False pour « ([)] » (sommet incompatible à la fermeture). La discipline LIFO de la pile capture exactement l'imbrication correcte des parenthèses.

Objectif Bac

  • Objectif Bac : dérouler à la main une suite d'empilements/dépilements ou d'enfilements/défilements et donner l'état final, ou la valeur renvoyée par chaque dépiler/défiler.
  • Objectif Bac : écrire les opérations de base d'une pile (empiler, dépiler, est_vide, sommet) ou d'une file (enfiler, défiler, est_vide), et reconnaître si un usage donné relève d'une pile ou d'une file.

Erreurs fréquentes

  • Confondre pile et file : utiliser une pile (LIFO) là où l'ordre d'arrivée doit être respecté, alors qu'une file (FIFO) est requise (par exemple une file d'attente d'impression).
  • Appeler dépiler / défiler sans tester est_vide au préalable : sur une structure vide, l'opération est indéfinie et lève une erreur (IndexError sur une liste Python).

Révision active

Implémentez une pile à l'aide d'une liste Python : écrivez les fonctions creer_pile(), est_vide(p), empiler(p, x), depiler(p) et sommet(p). Puis utilisez votre pile pour écrire bien_parenthesee(ch) qui teste si une chaîne formée de ( ) [ ] est correctement parenthésée.

Rappel actif

Rappelle-toi les points clés — puis révèle.

Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques (voie générale) — programmes et ressources (Éduscol — Ministère de l'Éducation nationale)

§ 04

Dictionnaires : clé, valeur et table de hachage#

●●○StandardLPeduscol-programme-nsi-terminale

Dictionnaire (table de hachage) : la clé est transformée en indice d'alvéole

Table de hachage : la clé devient un indice d'alvéoleGraphe, lundi → h(clé), mardi → h(clé), jeudi → h(clé), h(clé) → [1] = 5, h(clé) → [2] = 8, h(clé) → [4] = 2lundimardijeudih(clé)[1] = 5[2] = 8[4] = 2
Fig. 6La clé passe par la fonction de hachage h, qui calcule l'indice de son alvéole dans le tableau. D'où un accès, une insertion et un test d'appartenance en O(1) en moyenne (les collisions éventuelles sont gérées dans le tableau).

Points clés

Un dictionnaire associe à chaque clé une valeur (association clé → valeur). On accède à une valeur par sa clé, et non par une position : c'est un accès associatif, contrairement à l'accès par index d'une liste.
Les opérations usuelles sont : créer un dictionnaire, ajouter ou modifier un couple d[cle] = valeur, accéder à d[cle], tester l'appartenance d'une clé (cle in d), supprimer un couple, et parcourir l'ensemble des couples clé-valeur.
Le type dict de Python implémente le dictionnaire par une table de hachage : une fonction de hachage h transforme la clé en un indice de tableau (une alvéole), ce qui permet un accès direct à la valeur.
Grâce au hachage, l'accès, l'insertion et le test d'appartenance par clé sont en temps quasi constant O(1) en moyenne — bien plus rapide qu'une recherche séquentielle O(n) dans une liste de couples.
Les clés d'un dictionnaire Python doivent être hachables et sont uniques : affecter d[cle] avec une clé déjà présente remplace l'ancienne valeur. On peut parcourir les clés (for c in d), les valeurs (d.values()) ou les couples (d.items()).
On peut implémenter un dictionnaire au moyen d'une autre structure, par exemple une liste de couples (clé, valeur) ; mais la recherche d'une clé y est alors séquentielle, donc en O(n), d'où l'intérêt de la table de hachage.
h:cleˊ⟼indice d’alveˊole⇒acceˋs par cleˊ en O(1) (en moyenne)h : \text{clé} \longmapsto \text{indice d'alvéole} \quad\Rightarrow\quad \text{accès par clé en } \mathcal{O}(1) \text{ (en moyenne)}h:cleˊ⟼indice d’alveˊole⇒acceˋs par cleˊ en O(1) (en moyenne)

Principe de la table de hachage

La fonction de hachage h calcule directement l'indice où ranger (ou retrouver) la valeur, d'où un accès quasi instantané.

liste de couples:recherche d’une cleˊ en O(n)vsdict:O(1) en moyenne\text{liste de couples} : \text{recherche d'une clé en } \mathcal{O}(n) \quad\text{vs}\quad \text{dict} : \mathcal{O}(1) \text{ en moyenne}liste de couples:recherche d’une cleˊ en O(n)vsdict:O(1) en moyenne

Dictionnaire contre liste de couples

Chercher une clé dans une liste de n couples exige de la parcourir (O(n)) ; la table de hachage évite ce parcours.

Exemple corrigé

Compter les occurrences des lettres d'un mot avec un dictionnaire

Écrivez compter_lettres(mot) qui renvoie un dictionnaire {lettre : nombre d'occurrences}, et déroulez-le sur « banane ».

  1. 01Initialiser

    On part d'un dictionnaire vide d = {}. Il associera chaque lettre rencontrée à son compteur.

  2. 02Parcourir le mot

    Pour chaque lettre du mot : si la lettre est déjà une clé de d (lettre in d), on incrémente d[lettre] ; sinon on crée le couple d[lettre] = 1. Le test in s'appuie sur le hachage, en O(1) moyen.

  3. 03Dérouler « banane »

    b → {b:1} ; a → {b:1, a:1} ; n → {b:1, a:1, n:1} ; a → a déjà présent, {b:1, a:2, n:1} ; n → {b:1, a:2, n:2} ; e → {b:1, a:2, n:2, e:1}.

  4. 04Coût

    Chaque lettre déclenche un test d'appartenance et une mise à jour en O(1) moyen ; pour un mot de longueur n, le total est O(n).

Résultat : compter_lettres('banane') renvoie {'b': 1, 'a': 2, 'n': 2, 'e': 1}. Le dictionnaire permet un comptage direct par clé, là où une liste de couples imposerait une recherche séquentielle à chaque lettre.

Objectif Bac

  • Objectif Bac : utiliser un dictionnaire pour modéliser une association (comptage d'occurrences, annuaire, table de correspondance) et parcourir ses couples clé-valeur.
  • Objectif Bac : justifier l'avantage d'un dictionnaire (accès par clé en O(1) moyen) face à une liste de couples (recherche en O(n)).

Erreurs fréquentes

  • Croire qu'un dictionnaire est ordonné par valeurs de clés ou indexé par des positions entières : on accède par clé, et l'ordre des couples n'est pas un ordre de tri.
  • Accéder à d[cle] pour une clé absente, ce qui lève une KeyError : il faut d'abord tester cle in d (ou utiliser d.get(cle)).

Révision active

Écrivez compter_lettres(mot) qui renvoie un dictionnaire associant à chaque lettre de mot son nombre d'occurrences. Par exemple, compter_lettres('banane') doit donner {'b': 1, 'a': 2, 'n': 2, 'e': 1}.

Rappel actif

Rappelle-toi les points clés — puis révèle.

Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques (voie générale) — programmes et ressources (Éduscol — Ministère de l'Éducation nationale)

§ 05

Choisir et implémenter la structure adaptée à un problème#

●●●ApprofondissementLPeduscol-programme-nsi-terminale

Croissance du coût : accès par clé en O(1) (dictionnaire) contre O(n) (liste de couples)

Recherche par cle : dictionnaire O(1) vs liste de couples O(n)Courbe de liste : O(n), croissante, sur l’intervalle x de 1 à 30, Courbe de dico : O(1), sur l’intervalle x de 1 à 305101520253051015202530liste : O(n)dico : O(1)coût d'une recherche par clétaille n des données

Points clés

Choisir une structure de données revient à identifier les opérations dominantes du problème (accès, insertion, suppression, recherche par clé, ordre de traitement) et à retenir la structure qui les rend efficaces.
Repère LIFO/FIFO : si le dernier élément arrivé doit être traité en premier (annulation, parcours en profondeur, pile d'appels), c'est une pile ; si l'ordre d'arrivée doit être respecté (file d'attente, tampon, parcours en largeur), c'est une file.
Repère accès : accès par position (indice) → liste/tableau ; accès par clé symbolique → dictionnaire ; accès uniquement aux extrémités selon une discipline → pile ou file.
Implémenter une structure à l'aide d'une autre est courant : une pile et une file se réalisent avec une liste ; un dictionnaire se réalise (naïvement) avec une liste de couples, ou (efficacement) avec une table de hachage.
Tableau récapitulatif des coûts moyens : accès par indice — liste O(1), chaînée O(n) ; insertion en tête — liste O(n), chaînée O(1), pile/file O(1) ; recherche par clé — liste de couples O(n), dictionnaire O(1) en moyenne.
Justifier le choix, c'est nommer l'opération critique et son coût dans chaque structure candidate, puis conclure : un bon choix peut faire passer un algorithme de O(n²) à O(n).
couˆt total=(nombre d’opeˊrations)×(couˆt unitaire de l’opeˊration dominante)\text{coût total} = (\text{nombre d'opérations}) \times (\text{coût unitaire de l'opération dominante})couˆt total=(nombre d’opeˊrations)×(couˆt unitaire de l’opeˊration dominante)

Principe du choix par le coût

Le bon choix de structure minimise le coût unitaire de l'opération répétée le plus souvent.

Exemple corrigé

Choisir et justifier les structures d'une file d'impression

Un logiciel gère les travaux envoyés à une imprimante : ils doivent être imprimés dans l'ordre d'arrivée, et l'on veut pouvoir retrouver instantanément le propriétaire d'un travail à partir de son identifiant. Choisissez les structures adaptées et justifiez par le coût des opérations.

  1. 01Identifier les opérations

    Besoin 1 : traiter les travaux dans l'ordre d'arrivée (on ajoute à la fin, on retire au début). Besoin 2 : retrouver un propriétaire à partir d'un identifiant (accès par clé, répété).

  2. 02Besoin 1 → file (FIFO)

    L'ordre d'arrivée doit être respecté : c'est exactement la discipline FIFO d'une file. Enfiler en queue et défiler en tête (avec collections.deque) coûtent O(1).

  3. 03Besoin 2 → dictionnaire

    On veut un accès direct par identifiant : un dictionnaire identifiant → propriétaire donne cet accès en O(1) en moyenne. Une liste de couples imposerait une recherche séquentielle en O(n) à chaque requête.

  4. 04Conclusion chiffrée

    Pour q requêtes sur n travaux, la liste de couples coûte O(q·n) tandis que le dictionnaire coûte O(q) en moyenne : le gain est décisif quand n grandit.

Résultat : On choisit une file (FIFO) pour l'ordre d'impression — enfiler/défiler en O(1) — et un dictionnaire identifiant → propriétaire pour l'accès par clé en O(1) moyen, là où une liste de couples donnerait O(n) par requête. Le choix est justifié par le coût des opérations dominantes.

Schritt-für-Schritt Erklärung5 Schritte
  1. 1

    Tout part d'une question : quelle est l'opération que mon programme va répéter le plus souvent ?

  2. 2

    Si je dois respecter l'ordre d'arrivée — imprimer les documents dans l'ordre où ils ont été envoyés — la discipline est FIFO : je choisis une file.

  3. 3

    Si au contraire je veux retrouver une valeur à partir d'une clé symbolique, par exemple le propriétaire d'un travail à partir de son identifiant, je choisis un dictionnaire.

  4. 4

    La justification est toujours chiffrée : recherche par clé dans une liste de couples, O(n) par requête ; dans un dictionnaire, O(1) en moyenne. L'écart se creuse vite.

  5. 5

    Bien choisir sa structure de données, ce n'est donc pas un détail : cela peut faire passer un algorithme de O(n carré) à O(n).

Objectif Bac

  • Objectif Bac : face à une situation décrite en français, choisir la structure (liste, pile, file ou dictionnaire) et JUSTIFIER le choix par le coût des opérations dominantes.
  • Objectif Bac : implémenter une structure au moyen d'une autre (par exemple une file à l'aide d'une liste) et en commenter le coût.

Erreurs fréquentes

  • Choisir une structure « par habitude » (toujours une liste) sans regarder l'opération dominante : une recherche par clé répétée dans une liste donne O(n) par requête, là où un dictionnaire donne O(1) en moyenne.
  • Justifier un choix sans argument de coût : dire « c'est plus pratique » ne suffit pas, il faut comparer les complexités des opérations critiques.

Révision active

Un logiciel doit gérer les travaux envoyés à une imprimante (traités dans l'ordre d'arrivée) et retrouver instantanément, à partir d'un identifiant de travail, son propriétaire. Quelles structures de données choisissez-vous pour chaque besoin ? Justifiez par le coût des opérations.

Rappel actif

Rappelle-toi les points clés — puis révèle.

Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques (voie générale) — programmes et ressources (Éduscol — Ministère de l'Éducation nationale)

Sommaire

Section -- / 05

    • 01Type abstrait : interface contre implémentation○
    • 02Listes : tableaux dynamiques et listes chaînées◐
    • 03Piles (LIFO) et files (FIFO) : opérations et applications◐
    • 04Dictionnaires : clé, valeur et table de hachage◐
    • 05Choisir et implémenter la structure adaptée à un problème●

0/5 Lues

Des fiches à l'entraînement

Structures de données linéaires

Consolide ce thème avec des questions de la banque de questions.

~19
min
4
Compétences
S'entraîner

Références et sources

Sources

Ministère de l'Éducation nationale

  • Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019

Éduscol — Ministère de l'Éducation nationale

  • Numérique et sciences informatiques (voie générale) — programmes et ressources

Chapitre précédent

Histoire de l'informatique

Chapitre suivant

Arbres et graphes

EuraStudy·Fiches T·02·MMXXVI

Continuez avec le chapitre suivant — le parcours est conservé.