std::list în C++ cu Exemplu

⚡ Rezumat inteligent

std::list în C++ este un container de secvențe implementat ca o listă dublu înlănțuită, permițând inserarea și ștergerea rapidă în orice poziție, stocând în același timp elementele în memoria necontiguă și suportând accesul secvențial bidirecțional în loc de accesul aleatoriu.

  • 🔗 Listă dublu legată: Fiecare element păstrează legături către nodul anterior și următor, astfel încât datele std::list se află în memoria necontiguă.
  • Inserare și ștergere rapidă: Adăugarea sau eliminarea unui element într-o poziție cunoscută este o operațiune în timp constant, spre deosebire de un vector care deplasează elementele.
  • 🚫 Fără acces aleatoriu: Elementele sunt accesate prin traversare secvențială de la oricare dintre capete, deci indexarea precum lista[3] nu este disponibilă.
  • 🧩 Constructori: Constructorii implicit, de umplere, de interval, de copiere, de mutare și de listă de inițializare construiesc o listă std::list în moduri diferite.
  • 🛠️ Funcții ale membrilor: push_front(), push_back(), insert(), erase(), size(), reverse() și merge() gestionează conținutul listei.
  • 🤖 Asistență AI: GitHub Copilot și asistenți similari creează structuri de tip schelet pentru declarații std::list, iteratori și inserează sau șterg logica dintr-un comentariu scurt.

std::list în C++

Ce este o listă std::?

In C++, std::list se referă la un container de stocare. std::list vă permite să inserați și să eliminați elemente de oriunde. std::list este implementat ca o listă dublu legată. Aceasta înseamnă că datele listei pot fi accesate bidirecțional și secvențial.

Lista Bibliotecii de șabloane standard nu acceptă acces aleatoriu rapid, dar acceptă acces secvențial din toate direcțiile.

Puteți împrăștia elementele listei în diferite bucăți de memorie. Informațiile necesare pentru accesul secvenţial la date sunt stocate într-un container. Std::list se poate extinde și micșora de la ambele capete după cum este necesar în timpul rulării. Un alocator intern îndeplinește automat cerințele de stocare.

Aceste trăsături ridică o întrebare practică: când ar trebui să apelezi de fapt la o listă?

De ce să folosiți std::list?

Iată motivele pentru utilizarea std::list:

  • std::list se comportă mai bine în comparație cu alte containere de secvențe, cum ar fi array și vector.
  • Au o performanță mai bună la inserare, mișcare și extracțietracelemente de fixare din orice poziție.
  • De asemenea, std::list se descurcă mai bine cu algoritmii care efectuează astfel de operațiuni intens.

Având motivele clare, următorul pas este sintaxa care declară unul.

Sintaxa listei

Pentru a defini lista std::, trebuie să importam fișier antet. Iată sintaxa definiției std::list:

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

Iată o descriere a parametrilor de mai sus:

  • T – Definește tipul elementului conținut. Puteți înlocui T cu orice tip de date, chiar și cu tipuri definite de utilizator.
  • Alloc – Definește tipul obiectului allocator. Acesta utilizează implicit șablonul clasei allocator. Este dependent de valoare și folosește un model simplu de alocare a memoriei.

Exemplu 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';
	}
}

ieșire:

Rezultatul exemplului de creare și iterație std::list

Iată o captură de ecran a codului:

C++ cod care creează o listă std::list și o afișează cu o buclă for

Code Explicaţie:

  1. Includeți fișierul antet al algoritmului pentru a-i folosi funcțiile.
  2. Includeți fișierul antet iostream pentru a-i folosi funcțiile.
  3. Includeți fișierul antet listei pentru a utiliza funcțiile acestuia.
  4. Apelați funcția main(). Logica programului ar trebui adăugată în corpul acestei funcții.
  5. Creați o listă numită my_list cu un set de 4 numere întregi.
  6. Folosi pentru bucla pentru a crea o variabilă de buclă x. Această variabilă va fi utilizată pentru a itera peste elementele listei.
  7. Tipăriți valorile listei pe consolă.
  8. Capătul corpului buclei for.
  9. Sfârșitul corpului funcției main().

C++ Lista de funcții

Iată funcțiile comune std::list:

Funcţie Descriere
introduce() Această funcție inserează un nou element înainte de poziția indicată de iterator.
împinge înapoi() Această funcție adaugă un articol nou la sfârșitul listei.
push_front() Se adaugă un element nou în partea de față a listei.
pop_front() Acesta șterge primul element al listei.
mărimea() Această funcție determină numărul de elemente din listă.
față() Pentru a determina primele elemente ale listei.
înapoi() Pentru a determina ultimul element al listei.
verso() Acesta inversează elementele din listă.
combina() Îmbină două liste sortate.

Constructorii

Iată lista cu funcții furnizate de fișier antet:

  • Constructor implicit std::list::list()- creează o listă goală, care, cu zero elemente.
  • Constructor de umplere std::list::list() - Creează o listă cu n elemente și atribuie o valoare de zero (0) fiecărui element.
  • Constructorul de interval std::list::list()- creează o listă cu multe elemente în intervalul de la primul până la ultimul.
  • Copy constructor std::list::list()- Creează o listă cu o copie a fiecărui element conținut în lista existentă.
  • Move constructor std::list::list()- creează o listă cu elementele unei alte liste folosind semantica mutarii.
  • Constructorul listei de inițializare std::list::list()-Creează o listă cu elementele unei alte liste folosind semantica de mutare.

Exemplu 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;
}

ieșire:

Rezultatul exemplului de constructori std::list

Iată o captură de ecran a codului:

C++ cod care demonstrează constructorii std::list default, range și move

Code Explicaţie:

  1. Includeți fișierul antet iostream pentru a-i folosi funcțiile.
  2. Includeți fișierul antet listei pentru a utiliza funcțiile acestuia.
  3. Includeți spațiul de nume std în cod pentru a-și folosi clasele fără a-l apela.
  4. Apelați funcția main(). Logica programului ar trebui adăugată în corpul acestei funcții.
  5. Creați o listă goală numită l.
  6. Creați o listă numită l1 cu un set de 3 numere întregi.
  7. Creați o listă numită l2 cu toate elementele din lista numită l1, de la început până la sfârșit.
  8. Creați o listă numită l3 folosind semantica de mutare. Lista l3 va avea același conținut ca și lista l2.
  9. Tipăriți dimensiunea listei numite l pe consolă alături de alt text.
  10. Tipăriți ceva text pe consolă.
  11. Creați un iterator numit și utilizați-l pentru a itera elementele listei numite l2.
  12. Tipăriți elementele listei numite l2 pe consolă.
  13. Tipăriți ceva text pe consolă.
  14. Creați un iterator numit și utilizați-l pentru a itera elementele listei numite l3.
  15. Tipăriți elementele listei numite l3 pe consolă.
  16. Programul trebuie să returneze valoare după finalizarea cu succes.
  17. Sfârșitul corpului funcției main().

Proprietățile containerului

Iată lista proprietăților containerului:

Proprietatea Descriere
Secvenţă Containerele de secvențe își ordonează elementele într-o secvență liniară strictă. Elementele sunt accesate prin poziția lor în secvență.
Listă dublu legată Fiecare element are informații despre cum să localizați elementele anterioare și următoare. Acest lucru permite un timp constant pentru operațiunile de inserare și ștergere.
Conștient de alocător Un obiect alocător este utilizat pentru modificarea dinamică a dimensiunii stocării.

Inserarea într-o listă

Există diferite funcții pe care le putem folosi pentru a insera valori într-o listă. Să demonstrăm acest lucru:

Exemplu 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';
	}
}

ieșire:

Rezultat după inserarea elementelor într-o listă std::list

Iată o captură de ecran a codului:

C++ cod folosind push_front, push_back și inserare pe o listă std::list

Code Explicaţie:

  1. Includeți fișierul antet al algoritmului pentru a-i folosi funcțiile.
  2. Includeți fișierul antet iostream pentru a-i folosi funcțiile.
  3. Includeți fișierul antet listei pentru a utiliza funcțiile acestuia.
  4. Apelați funcția main(). Logica programului ar trebui adăugată în corpul acestei funcții.
  5. Creați o listă numită my_list cu un set de 4 numere întregi.
  6. Introduceți elementul 11 ​​în partea din față a listei numită my_list.
  7. Introduceți elementul 18 la sfârșitul listei numită my_list.
  8. Creați un iterator și folosiți-l pentru a găsi elementul 10 din lista my_list.
  9. Utilizați o declarație if pentru a determina dacă elementul de mai sus a fost găsit sau nu.
  10. Introduceți elementul 21 înaintea elementului de mai sus dacă a fost găsit.
  11. Sfârșitul corpului declarației if.
  12. Utilizați o buclă for pentru a crea o variabilă de buclă x. Această variabilă va fi folosită pentru a itera elementele listei.
  13. Tipăriți valorile listei pe consolă.
  14. Sfârșitul corpului buclei for.
  15. Sfârșitul corpului funcției main().

Elementele care intră într-o listă pot fi la fel de ușor eliminate.

Ștergerea dintr-o listă

Este posibil să ștergeți elemente dintr-o listă. Funcția erase() vă permite să ștergeți un element sau o gamă de elemente dintr-o listă.

  • Pentru a șterge un singur element, treceți pur și simplu cu o poziție întreagă. Elementul va fi șters.
  • Pentru a șterge un interval, transmiteți iteratorii de început și de sfârșit. Să demonstrăm acest lucru.

Exemplu 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;
}

ieșire:

Rezultat după ștergerea unui element dintr-o listă std::list

Iată o captură de ecran a codului:

C++ cod care folosește funcția erase pe o listă std::list

Code Explicaţie:

  1. Includeți fișierul antet al algoritmului pentru a-i folosi funcțiile.
  2. Includeți fișierul antet iostream pentru a-i folosi funcțiile.
  3. Includeți fișierul antet listei pentru a utiliza funcțiile acestuia.
  4. Includeți spațiul de nume std în programul nostru pentru a-i folosi clasele fără a-l apela.
  5. Apelați funcția main(). Logica programului ar trebui adăugată în corpul acestei funcții.
  6. Creați o listă numită my_list cu un set de 4 numere întregi.
  7. Tipăriți ceva text pe consolă.
  8. Utilizați o buclă for pentru a crea o variabilă de buclă x. Această variabilă va fi folosită pentru a itera elementele listei.
  9. Tipăriți valorile listei pe consolă.
  10. Capătul corpului buclei for.
  11. Creați un iterator i care indică primul element al listei.
  12. Utilizați funcția erase() indicată de iteratorul i.
  13. Tipăriți ceva text pe consolă.
  14. Utilizați o buclă for pentru a crea o variabilă de buclă x. Această variabilă va fi folosită pentru a itera elementele listei.
  15. Tipăriți valorile listei pe consolă. Aceasta vine după ștergere.
  16. Capătul corpului buclei for.
  17. Programul trebuie să returneze o valoare la finalizarea cu succes.
  18. Sfârșitul corpului funcției main().

Întrebări frecvente

std::vector stochează elementele în memoria contiguă cu acces aleator O(1), în timp ce std::list este o listă dublu înlănțuită care permite inserarea sau ștergerea O(1) oriunde. Alegeți vectorul pentru indexare și lista pentru inserțiile frecvente la mijloc.

Nu. std::list nu are un operator de acces aleatoriu, deci list[2] nu se compilează. Se ajunge la un element iterând de la begin() sau end() câte un nod pe rând, ceea ce costă un timp liniar O(n) pentru o poziție profundă.

std::list este o listă dublu înlănțuită care traversează ambele direcții și suportă push_back. std::forward_list este o listă înlănțuită simplu care se mișcă doar înainte, folosește mai puțină memorie per nod și nu oferă iteratori size() sau invers.

Apelați funcția membru my_list.sort(), care rulează în aproximativ N log N și menține elementele egale stabile. Algoritmul std::sort nu va funcționa deoarece are nevoie de iteratori cu acces aleatoriu. Transmiteți std::greater către sort() pentru ordinea descrescătoare.

Inserarea sau ștergerea unui nod costă un timp constant de O(1) odată ce un iterator este ținut în poziție, deoarece se schimbă doar pointerii vecini. Găsirea acelei poziții mai întâi prin parcurgere costă în continuare un timp de O(n).

Da. O funcție std::list nu este o mulțime, deci stochează liber valori repetate. Fiecare funcție push_back, push_front sau insert adaugă un nod nou, indiferent de conținutul existent. Folosește std::set atunci când trebuie să respingi elementele duplicate.

Da. Copilotul GitHub scrie declarații std::list, bucle de iterator și inserează sau șterge apeluri dintr-un comentariu scurt sau un nume de funcție. Adesea sugerează std::vector atunci când stocarea contiguă se potrivește mai bine sarcinii.

Asistenții de codare bazați pe inteligență artificială completează automat codul containerului STL, semnalează utilizarea greșită a iteratorului, convertesc o listă std::list într-o listă std::vector și explică compromisurile de complexitate. Aceștia accelerează învățarea codului STL, deși fiecare sugestie necesită încă o revizuire.

Rezumați această postare cu: