2009-04-10 13 views
19

Necesito asignar un par de long long a un double, pero no estoy seguro de qué función hash usar. Cada par puede consistir en dos números, aunque en la práctica generalmente serán números entre 0 y aproximadamente 100 (pero una vez más, eso no está garantizado).¿Función hash para un par de largo?

Here es la documentación tr1::unordered_map. Empecé como esto:

typedef long long Int; 
typedef std::pair<Int, Int> IntPair; 

struct IntPairHash { 
    size_t operator(const IntPair& p) const { 
    return ...; // how to hash the pair? 
    } 
}; 

struct IntPairEqual { 
    bool operator(const IntPair& a, const IntPair& b) const { 
    return a.first == b.first 
     && a.second == b.second; 
    } 
}; 

tr1::unordered_map<IntPair, double, IntPairHash, IntPairEqual> myMap; 

En general, nunca estoy seguro de qué función hash para su uso. ¿Cuál es una buena función hash de propósito general?

+21

¿Usted ha considerado el uso de una o más de las siguientes funciones hash propósito general: http://www.partow.net/programming/hashfunctions/index.html son extremadamente rápido y eficiente . –

Respuesta

1

¿Realmente necesita un mapa basado en hash? El mapa general basado en un árbol binario funcionará bien siempre que la complejidad garantice que funciona para el problema que está resolviendo.

+0

Hmm está bien, en ese caso, ¿cómo sería la función Comparar que compara dos IntPairs (la función 'less' para IntPairs)? –

+0

@Frank: forma más simple: (a.first

+0

Este (a.first

10

boost::hash biblioteca funcional de la forma.

o escriba el suyo. versión más simple = pair.first * max_second_value + pair.second

+0

+1 para la función. el enlace al boost :: hash sería genial. –

11

La forma natural de unir un par es combinar los hash de sus componentes de alguna manera. La forma más sencilla es sólo con XOR:

namespace std { 
namespace tr1 { 

template<typename a, typename b> 
struct hash< std::pair<a, b> > { 
private: 
    const hash<a> ah; 
    const hash<b> bh; 
public: 
    hash() : ah(), bh() {} 
    size_t operator()(const std::pair<a, b> &p) const { 
     return ah(p.first)^bh(p.second); 
    } 
}; 

}} // namespaces 

Tenga en cuenta que este hash pares como (1,1) o (2,2) todos a cero, por lo que es posible que desee utilizar alguna forma más compleja de combinar la hash de las partes, según sus datos. Boost hace algo como esto:

size_t seed = ah(p.first); 
return bh(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2); 
+1

Lea boost hash.hpp con más cuidado. Bost hace algo como esto: seed = hash (first) + 0x9e3779b9 + (seed <<6) + (seed>> 2); return seed^(hash (second) + 0x9e3779b9 + (semilla <<6) + (seed>> 2)); – velkyel

Cuestiones relacionadas