std :: liste dans C++ avec exemple

⚡ Résumé intelligent

std :: liste dans C++ est un conteneur de séquence implémenté sous forme de liste doublement chaînée, permettant une insertion et une suppression rapides à n'importe quelle position tout en stockant les éléments dans une mémoire non contiguë et en prenant en charge un accès séquentiel bidirectionnel au lieu d'un accès aléatoire.

  • 🔗 Liste doublement chaînée : Chaque élément conserve des liens vers son nœud précédent et suivant, de sorte que les données de std::list résident dans une mémoire non contiguë.
  • | Insertion et suppression rapides : L'ajout ou la suppression d'un élément à une position connue s'effectue en temps constant, contrairement à un vecteur qui décale ses éléments.
  • 🚫 Pas d'accès aléatoire : Les éléments sont atteints par parcours séquentiel à partir de l'une ou l'autre extrémité, donc l'indexation telle que list[3] n'est pas disponible.
  • 🧩 Constructeurs: Les constructeurs Default, fill, range, copy, move et initializer-list construisent un std::list de différentes manières.
  • Fonctions des membres : Les fonctions push_front(), push_back(), insert(), erase(), size(), reverse() et merge() gèrent le contenu de la liste.
  • 🤖 Aide à l'IA : GitHub Copilot et les assistants similaires génèrent les déclarations std::list, les itérateurs et la logique d'insertion ou de suppression à partir d'un court commentaire.

std :: liste dans C++

Qu'est-ce qu'une liste std :: ?

In C++`std::list` désigne un conteneur de stockage. `std::list` permet d'insérer et de supprimer des éléments à partir de n'importe quel emplacement. `std::list` est implémentée comme une liste doublement chaînée, ce qui signifie que les données de la liste sont accessibles de manière bidirectionnelle et séquentielle.

La liste de la bibliothèque de modèles standard ne prend pas en charge l'accès aléatoire rapide, mais elle prend en charge l'accès séquentiel dans toutes les directions.

Vous pouvez disperser les éléments de la liste dans différents blocs de mémoire. Les informations nécessaires à l'accès séquentiel aux données sont stockées dans un conteneur. La std::list peut s'étendre et se réduire des deux côtés selon les besoins pendant l'exécution. Un allocateur interne répond automatiquement aux exigences de stockage.

Ces caractéristiques soulèvent une question pratique : quand faut-il réellement recourir à une liste ?

Pourquoi utiliser std :: list ?

Voici les raisons d'utiliser std::list :

  • La classe std::list est plus performante que d'autres conteneurs de séquences comme les tableaux et les vecteurs.
  • Ils offrent de meilleures performances en matière d'insertion, de déplacement et d'extraction.tracéléments de ting depuis n'importe quelle position.
  • Le std::list fait également mieux avec les algorithmes qui effectuent de telles opérations de manière intensive.

Les raisons étant claires, l'étape suivante consiste à définir la syntaxe qui en déclare une.

Syntaxe de liste

Pour définir la std::list, nous devons importer le En tête de fichier. Voici la syntaxe de définition std::list :

template < class Type, class Alloc =allocator<T> > class list;

Voici une description des paramètres ci-dessus :

  • T – Définit le type de l'élément contenu. Vous pouvez remplacer T par n'importe quel type de données, même des types définis par l'utilisateur.
  • Alloc – Définit le type de l'objet allocateur. Par défaut, il utilise le modèle de classe allocateur. Il dépend de la valeur et utilise un modèle d'allocation mémoire simple.

Exemple 1

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };

	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

Sortie :

Résultat de l'exemple de création et d'itération de std::list

Voici une capture d'écran du code :

C++ code créant une std::list et l'affichant avec une boucle for

Code Explication:

  1. Incluez le fichier d'en-tête de l'algorithme pour utiliser ses fonctions.
  2. Incluez le fichier d'en-tête iostream pour utiliser ses fonctions.
  3. Incluez le fichier d'en-tête de liste pour utiliser ses fonctions.
  4. Appelez la fonction main(). La logique du programme doit être ajoutée dans le corps de cette fonction.
  5. Créez une liste nommée my_list avec un ensemble de 4 entiers.
  6. Utiliser un pour la boucle pour créer une variable de boucle x. Cette variable sera utilisée pour parcourir les éléments de la liste.
  7. Imprimez les valeurs de la liste sur la console.
  8. Fin du corps de la boucle for.
  9. Fin du corps de la fonction main().

C++ Fonctions de liste

Voici les fonctions std::list courantes :

Fonction Description
insérer() Cette fonction insère un nouvel élément avant la position vers laquelle pointe l'itérateur.
repousser() Cette fonction ajoute un nouvel élément à la fin de la liste.
push_front() Il ajoute un nouvel élément au début de la liste.
pop_front() Il supprime le premier élément de la liste.
Taille() Cette fonction détermine le nombre d'éléments de la liste.
de face() To détermine les premiers éléments de la liste.
dos() To détermine le dernier élément de la liste.
inverser () Il inverse les éléments de la liste.
fusionner() Il fusionne deux listes triées.

Constructeurs

Voici la liste des fonctions fournis par le En tête de fichier:

  • Constructeur par défaut std::list::list() - Il crée une liste vide, avec zéro élément.
  • Constructeur de remplissage std::list::list()- Il crée une liste avec n éléments et attribue une valeur de zéro (0) à chaque élément.
  • Constructeur de plage std::list::list()- crée une liste avec de nombreux éléments compris entre le premier et le dernier.
  • Constructeur de copie std::list::list()- Il crée une liste avec une copie de chaque élément contenu dans la liste existante.
  • Constructeur de déplacement std::list::list()- crée une liste avec les éléments d'une autre liste en utilisant la sémantique de déplacement.
  • Constructeur de liste d'initialisation std::list::list() - Il crée une liste avec les éléments d'une autre liste en utilisant la sémantique de déplacement.

Exemple 2

#include <iostream>
#include <list>
using namespace std;
int main(void) {
	list<int> l;
	list<int> l1 = { 10, 20, 30 };
	list<int> l2(l1.begin(), l1.end());
	list<int> l3(move(l1));  
	cout << "Size of list l: " << l.size() << endl;
	cout << "List l2 contents: " << endl;
	for (auto it = l2.begin(); it != l2.end(); ++it)
	      cout << *it << endl;
	cout << "List l3 contents: " << endl;
	for (auto it = l3.begin(); it != l3.end(); ++it)
		cout << *it << endl;
	return 0;
}

Sortie :

Exemple de sortie des constructeurs de std::list

Voici une capture d'écran du code :

C++ Code illustrant les constructeurs par défaut, de plage et de déplacement de std::list

Code Explication:

  1. Incluez le fichier d'en-tête iostream pour utiliser ses fonctions.
  2. Incluez le fichier d'en-tête de liste pour utiliser ses fonctions.
  3. Incluez l'espace de noms std dans le code pour utiliser ses classes sans l'appeler.
  4. Appelez la fonction main(). La logique du programme doit être ajoutée dans le corps de cette fonction.
  5. Créez une liste vide nommée l.
  6. Créez une liste nommée l1 avec un ensemble de 3 entiers.
  7. Créez une liste nommée l2 avec tous les éléments de la liste nommée l1, du début à la fin.
  8. Créez une liste nommée l3 en utilisant la sémantique de déplacement. La liste l3 aura le même contenu que la liste l2.
  9. Imprimez la taille de la liste nommée l sur la console à côté d'un autre texte.
  10. Imprimez du texte sur la console.
  11. Créez un itérateur nommé et utilisez-le pour parcourir les éléments de la liste nommée l2.
  12. Imprime les éléments de la liste nommée l2 sur la console.
  13. Imprimez du texte sur la console.
  14. Créez un itérateur nommé et utilisez-le pour parcourir les éléments de la liste nommée l3.
  15. Imprime les éléments de la liste nommée l3 sur la console.
  16. Le programme doit renvoyer de la valeur une fois terminé.
  17. Fin du corps de la fonction main().

Propriétés du conteneur

Voici la liste des propriétés du conteneur :

Propriétés Description
Séquence Les conteneurs de séquence ordonnent leurs éléments dans une séquence linéaire stricte. Les éléments sont accessibles par leur position dans la séquence.
Liste à double chaînage Chaque élément contient des informations sur la façon de localiser les éléments précédents et suivants. Cela permet un temps constant pour les opérations d’insertion et de suppression.
Conscient de l'allocateur Un objet allocateur est utilisé pour modifier dynamiquement la taille du stockage.

Insérer dans une liste

Il existe différentes fonctions permettant d'insérer des valeurs dans une liste. Prenons l'exemple suivant :

Exemple 3

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	my_list.push_front(11);
	my_list.push_back(18);
	auto it = std::find(my_list.begin(), my_list.end(), 10);
	if (it != my_list.end()) {
		my_list.insert(it, 21);
	}
	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

Sortie :

Résultat après l'insertion d'éléments dans une std::list

Voici une capture d'écran du code :

C++ code utilisant push_front, push_back et insert sur une std::list

Code Explication:

  1. Incluez le fichier d'en-tête de l'algorithme pour utiliser ses fonctions.
  2. Incluez le fichier d'en-tête iostream pour utiliser ses fonctions.
  3. Incluez le fichier d'en-tête de liste pour utiliser ses fonctions.
  4. Appelez la fonction main(). La logique du programme doit être ajoutée dans le corps de cette fonction.
  5. Créez une liste nommée my_list avec un ensemble de 4 entiers.
  6. Insérez l'élément 11 au début de la liste nommée my_list.
  7. Insérez l'élément 18 à la fin de la liste nommée my_list.
  8. Créez un itérateur et utilisez-le pour trouver l'élément 10 de la liste my_list.
  9. Utilisez une instruction if pour déterminer si l'élément ci-dessus a été trouvé ou non.
  10. Insérez l'élément 21 avant l'élément ci-dessus s'il a été trouvé.
  11. Fin du corps de l'instruction if.
  12. Utilisez une boucle for pour créer une variable de boucle x. Cette variable sera utilisée pour parcourir les éléments de la liste.
  13. Imprimez les valeurs de la liste sur la console.
  14. Fin du corps de la boucle.
  15. Fin du corps de la fonction main().

Les éléments qui figurent dans une liste peuvent tout aussi facilement en être retirés.

Suppression d'une liste

Il est possible de supprimer des éléments d'une liste. La fonction erase() permet de supprimer un élément ou une plage d'éléments d'une liste.

  • Pour supprimer un seul élément, il vous suffit de passer une position entière. L'élément sera supprimé.
  • Pour supprimer une plage, vous devez fournir les itérateurs de début et de fin. Illustrons cela.

Exemple 4

#include <algorithm>
#include <iostream>
#include <list>
using namespace std;
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	cout << "List elements before deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	list<int>::iterator i = my_list.begin();
	my_list.erase(i);
	cout << "\nList elements after deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	return 0;
}

Sortie :

Résultat après la suppression d'un élément d'une std::list

Voici une capture d'écran du code :

C++ code utilisant la fonction erase sur une std::list

Code Explication:

  1. Incluez le fichier d'en-tête de l'algorithme pour utiliser ses fonctions.
  2. Incluez le fichier d'en-tête iostream pour utiliser ses fonctions.
  3. Incluez le fichier d'en-tête de liste pour utiliser ses fonctions.
  4. Incluez l'espace de noms std dans notre programme pour utiliser ses classes sans l'appeler.
  5. Appelez la fonction main(). La logique du programme doit être ajoutée dans le corps de cette fonction.
  6. Créez une liste nommée my_list avec un ensemble de 4 entiers.
  7. Imprimez du texte sur la console.
  8. Utilisez une boucle for pour créer une variable de boucle x. Cette variable sera utilisée pour parcourir les éléments de la liste.
  9. Imprimez les valeurs de la liste sur la console.
  10. Fin du corps de la boucle for.
  11. Créez un itérateur i qui pointe vers le premier élément de la liste.
  12. Utilisez la fonction effacer() pointée par l'itérateur i.
  13. Imprimez du texte sur la console.
  14. Utilisez une boucle for pour créer une variable de boucle x. Cette variable sera utilisée pour parcourir les éléments de la liste.
  15. Imprimez les valeurs de la liste sur la console. Cela vient après la suppression.
  16. Fin du corps de la boucle for.
  17. Le programme doit renvoyer une valeur une fois terminé.
  18. Fin du corps de la fonction main().

FAQ

std::vector stocke les éléments dans une zone mémoire contiguë avec un accès aléatoire en O(1), tandis que std::list est une liste doublement chaînée offrant une insertion ou une suppression en O(1) à n'importe quel endroit. Privilégiez vector pour l'indexation et list pour les insertions fréquentes au milieu de la liste.

Non. `std::list` ne possède pas d'opérateur d'accès aléatoire ; par conséquent, `list[2]` ne compile pas. Pour accéder à un élément, il faut itérer `begin()` ou `end()` nœud par nœud, ce qui a une complexité temporelle linéaire O(n) pour une position profonde.

`std::list` est une liste doublement chaînée qui parcourt les deux sens et prend en charge `push_back`. `std::forward_list` est une liste simplement chaînée qui ne parcourt que l'élément dans l'autre sens, utilise moins de mémoire par nœud et ne propose pas de méthode `size()` ni d'itérateur inverse.

Appelez la fonction membre `my_list.sort()`, dont la complexité temporelle est d'environ N log N et qui préserve l'homogénéité des éléments. L'algorithme `std::sort` ne convient pas car il nécessite des itérateurs à accès aléatoire. Pour un tri décroissant, passez `std::greater` à `sort()`.

L'insertion ou la suppression d'un nœud s'effectue en temps constant O(1) une fois qu'un itérateur pointant vers sa position est défini, car seuls les pointeurs voisins sont modifiés. La recherche préalable de cette position par parcours prend toujours un temps O(n).

Oui. Une `std::list` n'est pas un ensemble, elle peut donc contenir des valeurs répétées. Chaque opération `push_back`, `push_front` ou `insert` ajoute un nouveau nœud, indépendamment de son contenu. Utilisez `std::set` lorsque vous devez rejeter les doublons.

Oui. Copilote GitHub Il génère des déclarations de std::list, des boucles d'itérateurs et des appels d'insertion ou de suppression à partir d'un court commentaire ou d'un nom de fonction. Il suggère souvent std::vector lorsque le stockage contigu est plus adapté à la tâche.

Les assistants de programmation IA complètent automatiquement le code des conteneurs STL, signalent les erreurs d'utilisation des itérateurs, convertissent les `std::list` en `std::vector` et expliquent les compromis en termes de complexité. Ils accélèrent l'apprentissage de la STL, même si chaque suggestion nécessite une vérification.

Résumez cet article avec :