順序付けられていないマップで完全なハッシュを実現したい。何かにマッピングされているコンパイル時の既知の文字列のセットがあります。それらの完全なハッシュ関数を生成したい。unordered_map のサイズを既知の文字列セットのサイズの 3 倍にすると、完全なハッシュ関数 (シード番号) を見つけることができました。その数を最小限にしたい。関連する質問ですが、より大きな順序付けられていないマップを使用すると、より高速なマップが得られるというのは本当ですか?
Google の CityHash 関数で遊んでみました: http://code.google.com/p/cityhash/
#include <sstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <city.h>
unsigned seed = 0;
const unsigned numberOfTestData = 100;
const unsigned sizeOfPreallocatedMap = 3 * numberOfTestData; // what is the minimum value of this
const unsigned chanceToFindPerfectHashFnSeed = 10000; // in number of iterations
bool foundPerfectHashSeed = false;
int minCollisionCount = 999;
class CityHash {
public:
uint64 operator()(const std::string& s) const {
// return CityHash64(s.c_str(), s.size());
return CityHash64WithSeed(s.c_str(), s.size(), seed);
}
};
class StringEqual {
public:
bool operator()(const std::string& left, const std::string& right) const {
return left == right;
}
};
template<typename T>
void mapTester(T& map)
{
for (unsigned i = 0; i < numberOfTestData; ++i) {
std::stringstream ss;
ss << "TestData_" << i;
map[ss.str()] = i;
}
int collisionCount = 0;
unsigned maxBucketSize = 0;
for (size_t i = 0; i < map.bucket_count(); ++i) {
if (map.bucket_size(i) > 1) {
collisionCount++;
if (maxBucketSize <= map.bucket_size(i))
maxBucketSize = map.bucket_size(i);
}
}
if (collisionCount < minCollisionCount) {
minCollisionCount = collisionCount;
std::cout << maxBucketSize << " collision count is " << collisionCount << " with seed " << seed << std::endl;
}
if (maxBucketSize == 0 && collisionCount == 0)
foundPerfectHashSeed = true;
}
int main() {
std::unordered_map<std::string, int> map;
mapTester(map);
for (; seed < chanceToFindPerfectHashFnSeed; ++seed) {
if (foundPerfectHashSeed)
break;
std::unordered_map<std::string, int, CityHash, StringEqual> cityMap(sizeOfPreallocatedMap);
mapTester(cityMap);
}
std::cout << (foundPerfectHashSeed ? "Found!" : "Not found!") << std::endl;
return 0;
}