Tabla de contenido
1. Introducción a la lista
En C++, std::list
es una clase contenedora proporcionada por la biblioteca estándar para el almacenamiento en cadena de datos. Una lista vinculada (lista) es una estructura de almacenamiento no continua en una unidad de almacenamiento física. El orden lógico de los elementos de datos se implementa a través de enlaces de puntero en la lista vinculada.
- Composición de la lista enlazada: la lista enlazada consta de una serie de nodos .
- La composición del nodo: 1. Campo de datos para almacenar elementos de datos 2. Campo de puntero para almacenar la dirección del siguiente nodo .
La lista vinculada en STL es una lista vinculada circular bidireccional . Dado que el método de almacenamiento de la lista vinculada no es un espacio de memoria continuo, el iterador en la lista vinculada solo admite movimientos hacia adelante y hacia atrás y es un iterador bidireccional .
2. La diferencia entre std::list y std::vector
-
Implementación de bajo nivel:
list
Se implementa mediante una lista doblemente enlazada, cada elemento contiene punteros al elemento anterior y siguiente. Esta implementación hace que la inserción y eliminación de elementos en cualquier lugar de la lista sea eficiente, pero tiene un rendimiento deficiente para el acceso aleatorio a los elementos.vector
Se implementa mediante una matriz dinámica y los elementos se almacenan continuamente en la memoria. Esta implementación hace que el rendimiento del acceso aleatorio a elementos sea muy bueno, pero insertar/eliminar elementos en el medio o al principio implica mover elementos y el rendimiento es relativamente bajo.
-
Cambio de tamaño dinámico:
list
El tamaño de puede crecer y reducirse dinámicamente porque utiliza una lista vinculada para almacenar elementos, y el rendimiento de las operaciones de inserción y eliminación es independiente del tamaño de la lista.vector
El tamaño también puede crecer dinámicamente, pero esto puede resultar en una gran cantidad de operaciones de copia de elementos y reasignación de memoria cuando es necesario reasignar la memoria.
-
Eficiencia de acceso:
list
No se admite el acceso aleatorio, solo el acceso secuencial mediante iteradores. Para escenarios que requieren operaciones frecuentes de inserción y eliminación,list
el rendimiento es mejor.vector
Admite acceso aleatorio, se puede acceder a los elementos directamente a través de subíndices. Para operaciones que requieren acceso aleatorio frecuente,vector
el rendimiento es mejor.
-
Uso de memoria:
list
Al almacenar elementos, además del valor del elemento en sí, se requiere espacio adicional para almacenar punteros a los elementos anterior y siguiente. Por lo tanto, suelevector
utilizar más memoria que .vector
Al almacenar un elemento, solo es necesario almacenar el valor del elemento en sí y alguna información de control adicional, por lo que generalmente usalist
menos memoria que .
-
Operaciones de inserción y eliminación:
list
Es eficiente para insertar y eliminar elementos en posiciones arbitrarias porque solo requiere modificar los punteros de elementos adyacentes y no requiere mover otros elementos.list
Hay una propiedad importante: ni las operaciones de inserción ni de eliminación harán que el iterador de la lista original deje de ser válido. Estovector
no es cierto en .vector
Es eficiente para insertar y eliminar elementos al final porque solo necesita operar al final de la matriz y no requiere mover otros elementos. Pero al insertar/eliminar elementos en el medio o al principio, es necesario mover otros elementos.
En resumen, la elección de utilizar list
o vector
depende de los escenarios y necesidades de aplicación específicos. Puede elegir esto si se requieren operaciones frecuentes de inserción y eliminación y no se requiere acceso aleatorio frecuente a elementos list
. Si necesita acceso aleatorio frecuente a elementos y menos operaciones de inserción y eliminación, puede elegirlo vector
. Además, si necesita realizar operaciones de inserción y eliminación en el medio del contenedor y la eficiencia del acceso no es alta, puede considerar usarlo list
.
3. Constructor de listas
Prototipo constructor | explicar | |
---|---|---|
1 | lista<T> lt | Constructor predeterminado, implementado mediante clases de plantilla. |
2 | lista(lt.begin(), lt.end()) | Copie los elementos en el intervalo lt[begin, end) a sí mismo |
3 | lista(n, Elemento) | El constructor copia n elementos a sí mismo. |
4 | lista (lista constante <) | constructor de copias |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void printVec(list<double> &v)
{
for (list<double>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
list<int> v2(v1.begin(), v1.end());
printVec(v2);
list<double> v3(5, 6.32);
printVec(v3);
list<double> v4(v3);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
10 20
10 20
6.32 6.32 6.32 6.32 6.32
6.32 6.32 6.32 6.32 6.32
Aviso:
Cuando la lista se utiliza como parámetro o valor de retorno de una función, no puede faltar el "&".
4. Asignación de lista
Prototipo de función: =, asignar | explicar | |
---|---|---|
1 | lista& operador=(lista constante <) | Sobrecargado = operador |
2 | asignar (comienzo, fin) | Copie y asigne los datos en el intervalo [comienzo, fin) a sí mismo |
3 | asignar(n, Elemento) | Asignar n copias de elementos a sí mismo |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
list<int> v2 = v1;
printVec(v2);
list<int> v3;
v3.assign(v1.begin(), v1.end());
printVec(v3);
list<int> v4;
v4.assign(6, 1);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
10 20
10 20
10 20
1 1 1 1 1 1
5. Operación de longitud de lista
Prototipo de función: vaciar, dimensionar, cambiar tamaño | explicar | |
---|---|---|
1 | vacío() | Determinar si el contenedor está vacío. |
2 | tamaño() | Devuelve el número de elementos en el contenedor. |
3 | cambiar tamaño(int núm) | Vuelva a especificar la longitud del contenedor a num. Si el contenedor se alarga, la nueva posición se llena con el valor predeterminado; si el contenedor se acorta, los elementos al final que exceden la longitud del contenedor se eliminan. |
4 | cambiar tamaño(int num, Elemento) | Vuelva a especificar la longitud del contenedor a num. Si el contenedor se alarga, la nueva posición se llena con el valor del Elemento; si el contenedor se acorta, los elementos al final que excedan la longitud del contenedor se eliminan. |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
if (v1.empty()) //判断是否为空
{
cout << "当前v1为空!" << endl;
}
v1.push_back(10); //添加元素
v1.push_back(20);
v1.push_back(30);
if (!v1.empty())
{
cout << "v1中元素个数:" << v1.size() << endl;
printVec(v1);
}
v1.resize(5);
printVec(v1);
v1.resize(10, 1);
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
当前v1为空!
v1中元素个数:3
10 20 30
10 20 30 0 0
10 20 30 0 0 1 1 1 1 1
6. Inserción y eliminación de listas
Prototipo de función: push_back, pop_back, insertar, borrar, borrar | explicar | |
---|---|---|
1 | push_back(Elemento) | Insertar elemento al final |
2 | pop_back() | Eliminar el último elemento |
3 | push_front(Elemento) | Insertar un elemento al principio del contenedor. |
4 | pop_front() | Retire el primer elemento del comienzo del contenedor. |
5 | insertar(iterador p, Elemento) | El iterador apunta a la posición p para insertar el elemento Elemento |
6 | insertar(iterador p, int n, Elemento) | El iterador apunta a la posición p e inserta n elementos Elemento |
7 | insertar(p,inicio del iterador,fin del iterador) | Inserte datos en el intervalo [inicio, fin) en la posición p, sin valor de retorno |
8 | borrar (iterador p) | Eliminar el elemento señalado por el iterador. |
9 | borrar (inicio del iterador, final del iterador) | Eliminar los elementos de principio a fin del iterador. |
10 | eliminar (elemento) | Eliminar todos los elementos en el contenedor que coincidan con el valor del elemento |
11 | claro() | Eliminar todos los elementos del contenedor. |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(1); //尾部添加元素
v1.push_back(2);
v1.push_back(3);
v1.push_back(3);
cout << "尾部添加元素: " << endl;
printVec(v1);
v1.pop_back(); //尾部删除元素
cout << "尾部删除元素: " << endl;
printVec(v1);
v1.push_front(100); //头部添加元素
v1.push_front(200);
v1.push_front(300);
cout << "头部添加元素: " << endl;
printVec(v1);
v1.pop_front(); //头部删除元素
v1.pop_front();
cout << "头部删除元素: " << endl;
printVec(v1);
v1.insert(v1.begin(), 100); //插入元素100
cout << "插入元素100: " << endl;
printVec(v1);
v1.insert(v1.begin(), 5, 100); //插入5个元素100
cout << "插入5个元素100: " << endl;
printVec(v1);
v1.erase(v1.begin()); //删除元素
cout << "删除元素v1.begin(): " << endl;
printVec(v1);
v1.remove(100);
cout << "删除所有100元素: " << endl;
printVec(v1);
v1.clear(); //清空容器
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
尾部添加元素:
1 2 3 3
尾部删除元素:
1 2 3
头部添加元素:
300 200 100 1 2 3
头部删除元素:
100 1 2 3
插入元素100:
100 100 1 2 3
插入5个元素100:
100 100 100 100 100 100 100 1 2 3
删除元素v1.begin():
100 100 100 100 100 100 1 2 3
删除所有100元素:
1 2 3
7. Adquisición de datos de lista
Prototipo de función: frente (), atrás | explicar | |
---|---|---|
1 | frente() | Devuelve el primer elemento de datos en el contenedor. |
2 | atrás() | Devuelve el último elemento de datos en el contenedor. |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void test01()
{
list<int> v1 = {
1, 2, 3, 4, 5, 6 };
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
//result
v1.front() = 1
v1.back() = 6
8. Intercambio, reversión y clasificación de listas.
Prototipo de función: intercambiar, invertir, ordenar | explicar | |
---|---|---|
1 | intercambiar (lista lt) | Intercambia los elementos en lt con sus propios elementos. |
2 | contrarrestar() | Lista enlazada inversa |
3 | clasificar() | Clasificación de listas enlazadas |
Ejemplo:
#include <iostream>
#include <list> //必须包含该头文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1 = {
9, 5, 7, 8, 6 };
list<int> v2 = {
5, 4, 3, 2, 1 };
v1.swap(v2); //互换v1与v2中的元素
cout << "list v1 : " ;
printVec(v1);
cout << "list v2 : " ;
printVec(v2);
v2.sort(); //链表排序
cout << "v2链表排序 : ";
printVec(v2);
v2.reverse(); //反转链表v2
cout << "v2反转链表 : ";
printVec(v2);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
list v1 : 5 4 3 2 1
list v2 : 9 5 7 8 6
v2链表排序 : 5 6 7 8 9
v2反转链表 : 9 8 7 6 5