Qual è la differenza tra i due? Voglio dire, i metodi sono tutti uguali. Quindi, per un utente, funzionano in modo identico.
È corretto??
Risposte:
Dal sommario SGI STL (datato ma ancora molto utile) di deque
:
Un deque è molto simile a un vettore: come il vettore, è una sequenza che supporta l'accesso casuale agli elementi, l'inserimento e la rimozione del tempo costante di elementi alla fine della sequenza e l'inserimento e la rimozione del tempo lineare di elementi nel mezzo.
Il modo principale in cui deque differisce dal vettore è che deque supporta anche l'inserimento e la rimozione a tempo costante di elementi all'inizio della sequenza. Inoltre, deque non ha funzioni membro analoghe a capacity () e reserve () di vector e non fornisce nessuna delle garanzie sulla validità dell'iteratore associate a tali funzioni membro.
Ecco il riepilogo list
dallo stesso sito:
Una lista è una lista doppiamente collegata. Cioè, è una sequenza che supporta sia l'attraversamento in avanti che all'indietro e l'inserimento e la rimozione di tempo costante (ammortizzato) di elementi all'inizio o alla fine o nel mezzo. Gli elenchi hanno l'importante proprietà che l'inserimento e lo splicing non invalidano gli iteratori degli elementi dell'elenco e che anche la rimozione invalida solo gli iteratori che puntano agli elementi rimossi. L'ordine degli iteratori può essere modificato (ovvero, list :: iterator potrebbe avere un predecessore o successore diverso dopo un'operazione di elenco rispetto a prima), ma gli iteratori stessi non verranno invalidati o puntati a elementi diversi a meno che tale invalidazione o la mutazione è esplicita.
In sintesi, i contenitori possono avere routine condivise ma le garanzie di tempo per tali routine differiscono da contenitore a contenitore . Questo è molto importante quando si considera quale di questi contenitori utilizzare per un'attività: tenere conto di come il contenitore verrà utilizzato più frequentemente (ad esempio, più per la ricerca che per l'inserimento / cancellazione) fa molto per indirizzarti al contenitore giusto .
Lasciami elencare le differenze:
Complessità
Insert/erase at the beginning in middle at the end
Deque: Amortized constant Linear Amortized constant
List: Constant Constant Constant
constant
e amortized constant
?
std::list
è fondamentalmente una lista doppiamente collegata.
std::deque
, d'altra parte, è implementato più simile std::vector
. Ha un tempo di accesso costante per indice, così come l'inserimento e la rimozione all'inizio e alla fine, che fornisce caratteristiche di prestazioni notevolmente diverse rispetto a un elenco.
Un'altra importante garanzia è il modo in cui ogni diverso contenitore archivia i propri dati in memoria:
Nota che il deque è stato progettato per provare a bilanciare i vantaggi di vector e list senza i rispettivi inconvenienti. È un contenitore particolarmente interessante nelle piattaforme con memoria limitata, ad esempio i microcontrollori.
La strategia di archiviazione della memoria viene spesso trascurata, tuttavia, è spesso uno dei motivi più importanti per selezionare il contenitore più adatto per una determinata applicazione.
No. Un deque supporta solo l'inserimento e l'eliminazione di O (1) nella parte anteriore e posteriore. Può, ad esempio, essere implementato in un vettore con avvolgimento. Dal momento che garantisce anche l'accesso casuale O (1), puoi essere certo che non sta usando (solo) una lista doppiamente collegata.
Le differenze di prestazioni sono state spiegate bene da altri. Volevo solo aggiungere che interfacce simili o addirittura identiche sono comuni nella programmazione orientata agli oggetti, parte della metodologia generale di scrittura di software orientato agli oggetti. Non dovresti IN NESSUN MODO presumere che due classi funzionino allo stesso modo semplicemente perché implementano la stessa interfaccia, non più di quanto dovresti presumere che un cavallo funzioni come un cane perché entrambe implementano attack () e make_noise ().
Ecco un codice proof-of-concept dell'uso di lista, mappa non ordinata che fornisce la ricerca O (1) e la manutenzione esatta di O (1) LRU. Ha bisogno degli iteratori (non cancellati) per sopravvivere alle operazioni di cancellazione. Pianificare l'utilizzo in una cache gestita da software arbitrariamente grande O (1) per i puntatori della CPU sulla memoria della GPU. Annuisce allo scheduler Linux O (1) (coda di esecuzione LRU <-> per processore). Unordered_map ha un accesso temporale costante tramite una tabella 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;
}
Tra eminenti differenze tra deque
elist
Per deque
:
Articoli conservati fianco a fianco;
Ottimizzato per l'aggiunta di dati da due lati (fronte, retro);
Elementi indicizzati da numeri (numeri interi).
Può essere esplorato dagli iteratori e anche dall'indice dell'elemento.
L'accesso ai dati è più veloce.
Per list
Elementi archiviati "casualmente" nella memoria;
Può essere esplorato solo dagli iteratori;
Ottimizzato per l'inserimento e la rimozione nel mezzo.
L'accesso temporale ai dati è più lento, lento nell'iterazione, a causa della sua posizione spaziale molto scarsa.
Gestisce molto bene elementi di grandi dimensioni
Puoi controllare anche il seguente link , che confronta le prestazioni tra i due contenitori STL (con std :: vector)
Spero di aver condiviso alcune informazioni utili.