Voglio memorizzare le stringhe e rilasciare ciascuna un numero ID univoco (un indice andrebbe bene). Avrei solo bisogno di una copia di ogni stringa e ho bisogno di una rapida ricerca. Controllo se la stringa esiste nella tabella abbastanza spesso da notare un impatto sulle prestazioni. Qual è il miglior contenitore da usare per questo e come posso cercare se la stringa esiste?per la ricerca rapida dei nomi
risposta
Vorrei suggerire tr1 :: unordered_map. È implementato come hashmap, quindi ha una complessità prevista di O (1) per le ricerche e un caso peggiore di O (n). C'è anche un'implementazione boost se il tuo compilatore non supporta tr1.
#include <string>
#include <iostream>
#include <tr1/unordered_map>
using namespace std;
int main()
{
tr1::unordered_map<string, int> table;
table["One"] = 1;
table["Two"] = 2;
cout << "find(\"One\") == " << boolalpha << (table.find("One") != table.end()) << endl;
cout << "find(\"Three\") == " << boolalpha << (table.find("Three") != table.end()) << endl;
return 0;
}
suona come un array funzionerebbe perfettamente dove l'indice è l'indice nell'array. Per verificare se esiste, assicurati solo che l'indice sia nei limiti dell'array e che la sua voce non sia NULL.
MODIFICA: se si ordina l'elenco, è sempre possibile utilizzare una ricerca binaria che dovrebbe avere una ricerca rapida.
MODIFICA: Inoltre, se si desidera cercare una stringa, è sempre possibile utilizzare anche std::map<std::string, int>
. Questo dovrebbe avere delle discrete velocità di ricerca.
Ho un problema di prestazioni con gli array, ho bisogno di logN –
wait in modo da poter essere in grado di dire esiste ("my_string")? –
Ho pensato che volessi essere in grado di fare: C [indice] per ottenere la stringa. –
Provare std :: map.
Le stringhe da cercare sono disponibili staticamente? Potresti voler dare un'occhiata a perfect hashing function
Il modo più semplice è usare std :: map.
funziona così:
#include <map>
using namespace std;
...
map<string, int> myContainer;
myContainer["foo"] = 5; // map string "foo" to id 5
// Now check if "foo" has been added to the container:
if (myContainer.find("foo") != myContainer.end())
{
// Yes!
cout << "The ID of foo is " << myContainer["foo"];
}
// Let's get "foo" out of it
myContainer.erase("foo")
Come ho commentato la risposta di @ Teran: Non sarebbe
ha detto che vuole cercare da una stringa nel commento a terans rispondere se gli ho dato giusto –
beh lui non ha ... ma supponiamo che abbia fatto :) –
In primo luogo è necessario essere in grado di quantificare i le opzioni. Ci hai anche detto che il modello di utilizzo principale che ti interessa è la ricerca , non l'inserimento.
Sia N
sia il numero di stringhe che si prevede di essere avere nella tabella, e lasciare che C
essere il numero medio di caratteri in un dato di stringa presenti in detta tabella (o nelle stringhe che vengono controllati contro il tavolo).
Nel caso di un approcciohash-based, per ogni ricerca si paga i seguenti costi:
O(C)
- calcolare l'hash per la stringa che si sta per guardare in alto- tra
O(1 x C)
eO(N x C)
, dove1..N
è il costo che ci si aspetta dall'attraversare il bucket in base alla chiave hash, qui moltiplicato perC
per ricontrollare i caratteri in ogni stringa contro la ricerca della chiave - tempo totale: tra il
O(2 x C)
eO((N + 1) x C)
Nel caso di un approccio basata su
std::map
(che utilizza alberi rosso-nero), per ogni ricerca si paga il costi seguenti:- tempo totale: tra
O(1 x C)
eO(log(N) x C)
- doveO(log(N))
è il costo massimo attraversamento di alberi, eO(C)
è il tempo che 0 genericless<>
implementaziones' prende di ricontrollare la vostra chiave di ricerca durante l'attraversamento di alberi
- tempo totale: tra
Nel caso di valori di grandi dimensioni per N
e in assenza di una funzione di hash che garantisce meno di registro collisioni (N), o se vuoi semplicemente giocare sul sicuro, , è meglio usare un approccio basato su albero (std::map
). Se N è piccolo, con tutti i mezzi, utilizzare un approccio basato su hash (., Pur facendo in modo che hash collisione è basso)
Prima di prendere qualsiasi decisione, però, si dovrebbe anche controllare:
Google sparse hash forse
provare questo:
Non utilizzare unordered_map in T1, non ha il metodo di riserva e se si inserisce un sacco di corda durante la fase di inserimento che si sta per avere un sacco di rimaneggiamento. –
Anche unordered_map per stringhe lunghe è peggiore di un std :: map –