Tableau vs liste chaînée : accès, insertion et suppression, disposition en mémoire, cache, complexité temporelle
Un tableau range des éléments de même type côte à côte en mémoire, sans trou, si bien que la position de n’importe quel élément se calcule à partir de son indice et qu’on peut le lire ou l’écrire en temps constant. Une liste chaînée est une structure de données dans laquelle chaque élément contient une valeur et un pointeur vers l’élément suivant ; les éléments sont reliés en suivant ces pointeurs et peuvent donc se trouver à des endroits différents de la mémoire. Un tableau se lit vite, mais insérer ou supprimer au milieu oblige à décaler les éléments qui suivent. Une liste chaînée peut insérer ou supprimer en changeant seulement des pointeurs une fois la position connue, mais lire le i-ième élément oblige à la parcourir depuis la tête. Règle de base : un tableau quand on lit surtout par indice, une liste chaînée quand on insère ou supprime souvent à des positions connues.
| Critère | Tableau | Liste chaînée |
|---|---|---|
| Disposition en mémoire | Les éléments sont côte à côte dans un seul bloc contigu | Les éléments sont dispersés et reliés par des pointeurs |
| Lecture du i-ième élément | O(1) : l’adresse vaut adresse de départ + i × taille d’un élément | O(n) : suivre i fois les pointeurs depuis la tête |
| Recherche d’une valeur | O(n) par recherche linéaire si non trié ; O(log n) par recherche dichotomique si trié | O(n), même si trié ; la recherche dichotomique est impossible faute de pouvoir sauter au milieu |
| Insertion ou suppression au milieu | O(n) : les éléments qui suivent sont décalés un à un | O(1) si la position (l’élément précédent) est connue ; seuls des pointeurs changent |
| Ajout en fin | O(1) s’il reste de la place ; un tableau dynamique qui double sa capacité recopie parfois tout, mais reste O(1) en moyenne (amorti) | O(1) si l’on conserve un pointeur vers le dernier élément |
| Redimensionnement | La taille d’un tableau de taille fixe est fixée à sa création ; l’agrandir impose d’allouer un nouveau bloc et de recopier | L’espace est alloué élément par élément : la liste ne grandit que du nécessaire |
| Mémoire utilisée | Seulement les éléments eux-mêmes (un tableau dynamique garde un peu de capacité de réserve) | Un pointeur supplémentaire par élément (deux dans une liste doublement chaînée) |
| Efficacité du cache | Bonne : les éléments sont contigus, donc une lecture séquentielle tire bien parti des caches et du préchargement | Mauvaise : les éléments ont tendance à être dispersés, donc même un parcours en O(n) identique peut être bien plus lent qu’avec un tableau |
| Usages typiques | Tables lues et écrites par indice, matrices et images, données à trier ou à rechercher par dichotomie, implémentation de piles et de files | Séquences avec insertions et suppressions fréquentes, chaînage dans les tables de hachage, gestion de l’espace libre |
Les valeurs indiquées sont des ordres de grandeur typiques et varient selon la génération de procédé et le produit.