2016-11-24 9 views
3

私はunordered_mapを別のunordered_mapをキーとして使用しようとしています(カスタムハッシュ関数)。おそらく必要ではないにしても、カスタム等価関数を追加しました。C++ unordered_mapここでkeyもunordered_map

コードは私が期待していることをしませんが、私は何が起こっているのか頭や尻尾を作ることはできません。なんらかの理由で、find()を実行してもequal関数は呼び出されません。これは私が期待しているものです。 ==を使用して2つのstd::unordered_mapオブジェクトの比較

unsigned long hashing_func(const unordered_map<char,int>& m) { 
    string str; 
    for (auto& e : m) 
     str += e.first; 
    return hash<string>()(str); 
} 
bool equal_func(const unordered_map<char,int>& m1, const unordered_map<char,int>& m2) { 
    return m1 == m2; 
} 

int main() { 

    unordered_map< 
     unordered_map<char,int>, 
     string, 
     function<unsigned long(const unordered_map<char,int>&)>, 
     function<bool(const unordered_map<char,int>&, const unordered_map<char,int>&)> 
     > mapResults(10, hashing_func, equal_func); 

    unordered_map<char,int> t1 = getMap(str1); 
    unordered_map<char,int> t2 = getMap(str2); 

    cout<<(t1 == t2)<<endl; // returns TRUE 
    mapResults[t1] = "asd"; 
    cout<<(mapResults.find(t2) != mapResults.end()); // returns FALSE 

    return 0; 
} 
+1

ハッシュ関数が2つのマップに対して返すものを見てください。 – Caleth

答えて

2

まず第一に、あなたがそれを維持する必要がありますので、等価演算子は確かに、必要とされます。

はのは、あなたの順序なしマップのハッシュ関数を見てみましょう:

string str; 
for (auto& e : m) 
    str += e.first; 
return hash<string>()(str); 

それは順不同マップですので、定義によって、イテレータは任意の順序で順不同のマップのキーを反復処理することができます。しかし、ハッシュ関数は同じキーに対して同じハッシュ値を生成する必要があるため、このハッシュ関数は明らかにその点で失敗します。

また、ハッシュ関数には、キーそのものに加えて、無秩序なマップキーの値も含まれることが期待されます。私はあなたがそれをこのようにしたいと思うかもしれないと思います - 2つの順序付けられていないマップは、キーが同じで、それらの値を無視する限り、同じキーとみなされるためです。あなたの期待が何であるかという疑問からは明らかではありませんが、あなたはそれを考えることができます。

+0

はい、問題でした。ハッシュ関数は同じキーに対して同じ値を返しませんでした。それは何とか私の心を逃れました。 –

2

は、マップが同じキーを含むかどうかを比較します。同じ順序でそれらが含まれているかどうかはわかりません(結局のところ、の番号はです)。ただし、hashing_funcは、マップ内のアイテムの順番によって異なります。hash<string>()("ab")は、通常hash<string>()("ba")とは異なります。

0

開始するには、各マップに対してhashing_funcが返すもの、またはhashing_funcの文字列構造が生成するものがより簡単です。そのようなタイプのため

より明らかに正しいハッシュ関数は次のようになります。

unsigned long hashing_func(const unordered_map<char,int>& m) { 
    unsigned long res = 0; 
    for (auto& e : m) 
     res^hash<char>()(e.first)^hash<int>()(e.second); 
    return res; 
} 
関連する問題