2013-06-14 3 views
6

Salve, avevo un set non ordinato per contenere il mio array int 16, ora ho bisogno di memorizzare un altro int come bucket. Mi chiedo se posso inserire l'array nel mio unordered_set, o posso usare lo stesso modello che usavo?C++ Come inserire la matrice in unordered_map come chiave?

#include <unordered_set> 
#include <array> 

namespace std 
{ 
    template<typename T, size_t N> 
    struct hash<array<T, N> > 
    { 
     typedef array<T, N> argument_type; 
     typedef size_t result_type; 

     result_type operator()(const argument_type& a) const 
     { 
      hash<T> hasher; 
      result_type h = 0; 
      for (result_type i = 0; i < N; ++i) 
      { 
       h = h * 31 + hasher(a[i]); 
      } 
      return h; 
     } 
    }; 
} 

std::unordered_set<std::array<int, 16> > closelist; 

int main() 
{ 
    std::array<int, 16> sn = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15}; 
    closelist.insert(sn); 
} 

Posso solo cambiarlo a questo?

std::unordered_map<std::array<int, 16>,int > closelist; 

    int main() 
    { 
     std::array<int, 16> sn = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15}; 
     closelist.insert(sn,24); 
    } 

E non riuscivo a capire il modello, mi chiedo che cosa è "H = h * 31 + Hasher (a [i]);"?

Grazie !!!

+0

_ "Mi chiedo cosa sia' h = h * 31 + hasher (a [i]); '" _ - In questa riga si calcola solo un hash per il proprio array. Che cosa esattamente non capisci? – soon

+0

@soon cosa è 31? Ho chiesto informazioni su questo e qualche bravo ragazzo mi ha dato questo modello ... – weeo

+0

'31' è solo una costante. Dipende dalle tue restrizioni per gli elementi in un array. – soon

risposta

1

Posso solo cambiarlo a questo?

In primo luogo, la vostra inizializzazione del campo è sbagliato:

std::array<int, 16> sn = {{1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15}}; 
//      ^         ^

Dal std::array non ha costruttore con std::initializer_list come argomento. Quindi, primo livello per inizializzare un oggetto, secondo per inizializzare una matrice nell'oggetto.

In secondo luogo, da reference:

std::pair<iterator,bool> insert(const value_type& value); 

template <class P> 
std::pair<iterator,bool> insert(P&& value); 

Quindi, si dovrebbe passare std::pair (o qualcosa del genere, convertibile in std::pair), ad esempio:

closelist.insert({sn,24}); 

Oppure, più semplice:

closelist[sn] = 24; 
1

Come usare qualsiasi oggetto come chiave:

  1. serializzare l'oggetto in un array di byte (per un array di int semplicemente utilizzare i dati binari come è)
  2. Calcola l'hash crittografico (MD5 o SHA)
  3. convertire il hash crittografico in un valore di impronte digitali (ad esempio lanciato i suoi primi 64 bit in uint64_t)
  4. usare questo impronte digitali come una mappa chiave

il disadvantag È che potresti aver bisogno di risolvere collisioni in qualche modo.

+0

Di solito non usi alcun hash crittografico _unless_ ne hai davvero bisogno. Gli hash crittografici sono computazionalmente più intensi. Inoltre, trovare una perfetta funzione di hash (senza collisioni per l'applicazione) è sempre una sfida. Nella maggior parte dei casi, l'implementazione standard funziona molto bene. –