¿Cuál es la diferencia entre los dos? Me refiero a que los métodos son todos iguales. Entonces, para un usuario, funcionan de manera idéntica.
¿¿Es eso correcto??
¿Cuál es la diferencia entre los dos? Me refiero a que los métodos son todos iguales. Entonces, para un usuario, funcionan de manera idéntica.
¿¿Es eso correcto??
Respuestas:
Del resumen SGI STL (fechado pero aún muy útil) de deque
:
Una deque es muy parecida a un vector: como un vector, es una secuencia que admite el acceso aleatorio a los elementos, la inserción y eliminación de elementos en tiempo constante al final de la secuencia, y la inserción y eliminación de elementos en el medio en el tiempo lineal.
La principal forma en que deque se diferencia del vector es que deque también admite la inserción y eliminación de elementos en tiempo constante al comienzo de la secuencia. Además, deque no tiene ninguna función miembro análoga a la capacidad del vector () y reserve (), y no proporciona ninguna de las garantías sobre la validez del iterador que están asociadas con esas funciones miembro.
Aquí está el resumen list
del mismo sitio:
Una lista es una lista doblemente enlazada. Es decir, es una Secuencia que admite tanto el recorrido hacia adelante como hacia atrás, y la inserción y eliminación de elementos en tiempo constante (amortizado) al principio o al final, o en el medio. Las listas tienen la propiedad importante de que la inserción y el empalme no invalidan los iteradores de los elementos de la lista, y que incluso la eliminación invalida solo los iteradores que apuntan a los elementos que se eliminan. El orden de los iteradores puede cambiarse (es decir, list :: iterator puede tener un predecesor o sucesor diferente después de una operación de lista que antes), pero los iteradores en sí no serán invalidados o hechos para apuntar a diferentes elementos a menos que esa invalidación o la mutación es explícita.
En resumen, los contenedores pueden tener rutinas compartidas, pero las garantías de tiempo para esas rutinas difieren de un contenedor a otro . Esto es muy importante al considerar cuál de estos contenedores usar para una tarea: tener en cuenta cómo se usará el contenedor con mayor frecuencia (por ejemplo, más para buscar que para insertar / eliminar) ayuda en gran medida a dirigirlo al contenedor correcto .
Déjame enumerar las diferencias:
Complejidad
Insert/erase at the beginning in middle at the end
Deque: Amortized constant Linear Amortized constant
List: Constant Constant Constant
constant
y amortized constant
?
std::list
es básicamente una lista doblemente enlazada.
std::deque
, por otro lado, se implementa más como std::vector
. Tiene un tiempo de acceso constante por índice, así como inserción y eliminación al principio y al final, lo que proporciona características de rendimiento dramáticamente diferentes a las de una lista.
Otra garantía importante es la forma en que cada contenedor diferente almacena sus datos en la memoria:
Tenga en cuenta que el deque fue diseñado para intentar equilibrar las ventajas del vector y la lista sin sus respectivos inconvenientes. Es un contenedor especialmente interesante en plataformas con memoria limitada, por ejemplo, microcontroladores.
La estrategia de almacenamiento de memoria a menudo se pasa por alto, sin embargo, con frecuencia es una de las razones más importantes para seleccionar el contenedor más adecuado para una determinada aplicación.
No. Una deque solo admite la inserción y eliminación de O (1) en la parte delantera y trasera. Puede, por ejemplo, implementarse en un vector con envoltura. Dado que también garantiza el acceso aleatorio O (1), puede estar seguro de que no está usando (solo) una lista doblemente vinculada.
Otros han explicado bien las diferencias de rendimiento. Solo quería agregar que interfaces similares o incluso idénticas son comunes en la programación orientada a objetos, parte de la metodología general de escritura de software orientado a objetos. DE NINGÚN MODO debe asumir que dos clases funcionan de la misma manera simplemente porque implementan la misma interfaz, más de lo que debe asumir que un caballo funciona como un perro porque ambas implementan attack () y make_noise ().
Aquí hay un uso de código de prueba de concepto de una lista, un mapa desordenado que brinda O (1) búsqueda y O (1) mantenimiento LRU exacto. Necesita los iteradores (no borrados) para sobrevivir a las operaciones de borrado. Planee usarlo en un caché administrado por software arbitrariamente grande O (1) para punteros de CPU en la memoria de GPU. Señala con la cabeza al programador de Linux O (1) (LRU <-> cola de ejecución por procesador). Unordered_map tiene acceso de tiempo constante a través de una tabla hash.
#include <iostream>
#include <list>
#include <unordered_map>
using namespace std;
struct MapEntry {
list<uint64_t>::iterator LRU_entry;
uint64_t CpuPtr;
};
typedef unordered_map<uint64_t,MapEntry> Table;
typedef list<uint64_t> FIFO;
FIFO LRU; // LRU list at a given priority
Table DeviceBuffer; // Table of device buffers
void Print(void){
for (FIFO::iterator l = LRU.begin(); l != LRU.end(); l++) {
std::cout<< "LRU entry "<< *l << " : " ;
std::cout<< "Buffer entry "<< DeviceBuffer[*l].CpuPtr <<endl;
}
}
int main()
{
LRU.push_back(0);
LRU.push_back(1);
LRU.push_back(2);
LRU.push_back(3);
LRU.push_back(4);
for (FIFO::iterator i = LRU.begin(); i != LRU.end(); i++) {
MapEntry ME = { i, *i};
DeviceBuffer[*i] = ME;
}
std::cout<< "************ Initial set of CpuPtrs" <<endl;
Print();
{
// Suppose evict an entry - find it via "key - memory address uin64_t" and remove from
// cache "tag" table AND LRU list with O(1) operations
uint64_t key=2;
LRU.erase(DeviceBuffer[2].LRU_entry);
DeviceBuffer.erase(2);
}
std::cout<< "************ Remove item 2 " <<endl;
Print();
{
// Insert a new allocation in both tag table, and LRU ordering wiith O(1) operations
uint64_t key=9;
LRU.push_front(key);
MapEntry ME = { LRU.begin(), key };
DeviceBuffer[key]=ME;
}
std::cout<< "************ Add item 9 " <<endl;
Print();
std::cout << "Victim "<<LRU.back()<<endl;
}
Entre las eminentes diferencias entre deque
ylist
Para deque
:
Elementos almacenados uno al lado del otro;
Optimizado para agregar datos desde dos lados (frontal, posterior);
Elementos indexados por números (enteros).
Puede ser examinado por iteradores e incluso por índice de elemento.
El tiempo de acceso a los datos es más rápido.
por list
Elementos almacenados "al azar" en la memoria;
Solo puede ser examinado por iteradores;
Optimizado para inserción y extracción en el medio.
El tiempo de acceso a los datos es más lento, más lento de iterar, debido a su escasa ubicación espacial.
Maneja muy bien elementos grandes
También puede consultar el siguiente enlace , que compara el rendimiento entre los dos contenedores STL (con std :: vector)
Espero haber compartido alguna información útil.