Chargement...

Structures séquentielles avec std::list et std::deque en C++

Apprenez à utiliser std::list et std::deque en C++, avec leurs différences de performances et leurs cas d’utilisation.

En C++, std::list et std::deque sont des structures de données séquentielles qui constituent des alternatives à std::vector lorsque différents comportements de performance sont nécessaires. std::list implémente une liste doublement chaînée, tandis que std::deque (double-ended queue) permet des insertions et suppressions rapides aux deux extrémités. Cet article explique quand utiliser l’une ou l’autre, avec des exemples pratiques.


1) Qu’est-ce que std::list ?

std::list est une liste doublement chaînée :


#include <list>
#include <iostream>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30};

    lst.push_front(5);   // ajouter au début
    lst.push_back(40);   // ajouter à la fin

    auto it = lst.begin();
    advance(it, 2);      // avancer de 2 positions
    lst.insert(it, 25);  // insertion au milieu

    for (int x : lst) cout << x << " ";
}

Cas d'utilisation : lorsque de nombreuses insertions/suppressions au milieu sont nécessaires.


2) Performances de std::list


// tri d’une liste
list<int> lst = {5, 2, 9, 1};
lst.sort();

3) Qu’est-ce que std::deque ?

std::deque est une structure double-ended queue (file à deux extrémités) permettant des opérations rapides aussi bien au début qu’à la fin.


#include <deque>
#include <iostream>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30};

    dq.push_front(5);
    dq.push_back(40);

    dq.pop_front();
    dq.pop_back();

    cout << dq[0] << endl;  // accès indexé possible
}

Cas d'utilisation : lorsque des opérations rapides en tête et en fin de structure sont nécessaires.


4) Performances de std::deque


5) Comparaison : list vs deque

Caractéristiquelistdeque
Accès aléatoire Non Oui (O(1))
Insertion rapide en tête O(1) O(1)
Insertion rapide en fin O(1) O(1)
Insertion au milieu O(1) O(n)
Structure mémoire Nœuds dispersés Blocs segmentés
Recommandé pour Nombreuses modifications au milieu Opérations rapides aux extrémités

6) Exemples pratiques : files de tâches et gestion d’entités

a) File de tâches avec deque


#include <deque>
#include <iostream>
using namespace std;

int main() {
    deque<string> tasks;

    tasks.push_back("Download");
    tasks.push_back("Parse");
    tasks.push_front("Init"); // tâche prioritaire

    while (!tasks.empty()) {
        cout << "Tâche: " << tasks.front() << endl;
        tasks.pop_front();
    }
}

b) Gestion d’entités dans un moteur de jeu avec list


#include <list>
#include <iostream>
using namespace std;

struct Entity {
    string name;
    Entity(string n) : name(n) {}
};

int main() {
    list<Entity> entities;

    entities.emplace_back("Player");
    entities.emplace_back("Enemy");
    entities.emplace_back("Tree");

    for (auto it = entities.begin(); it != entities.end(); ) {
        if (it->name == "Enemy")
            it = entities.erase(it);  // O(1)
        else
            ++it;
    }

    for (auto& e : entities)
        cout << e.name << endl;
}

7) Quel conteneur choisir ?

Règle générale : Essayez d’abord vector. S’il ne répond pas aux besoins, utilisez deque ou list.


8) TL;DR

  • list : liste doublement chaînée → O(1) au milieu, pas d’accès aléatoire.
  • deque : file à deux extrémités → O(1) en tête/queue, accès par indice disponible.
  • deque n’est pas entièrement contigu ; list consomme plus de mémoire.
  • Le profilage est la méthode la plus fiable pour comprendre les performances réelles.
  • Exemples compatibles Visual Studio 2022 et GCC 11+.

Articles connexes