我编写了一个基本程序,该程序接受字符串并通过将它们插入字符串->整数哈希映射来计算唯一字符串的发生率。
我使用 std::tr1::unordered_map 进行存储,为自定义哈希函数和自定义相等函数模板化。关键类型实际上是char*
而不是 too-slow std::string
。
然后,我更改了相同的代码以使用一个非常非常简单的哈希表(实际上是一个由哈希索引的 {key, value} 结构的数组),其大小为 2 的幂,并且对冲突进行线性探测。该程序的速度提高了 33%。
考虑到当我使用 tr1::unordered_map 时,我预先设置了哈希表的大小,因此它永远不必增长,并且我使用完全相同的哈希和比较例程,所以 tr1::unordered_map 这样做会使其速度减慢 50%与可以想象的最基本的哈希图相比?
我在这里所说的“简单”哈希映射类型的代码:
typedef struct dataitem {
char* item;
size_t count;
} dataitem_t;
dataitem_t hashtable[HASHTABLE_SIZE] = {{NULL,0}}; // Start off with empty table
void insert(char* item) {
size_t hash = generate_hash(item);
size_t firsthash = hash;
while (true) {
hash &= HASHTABLE_SIZE_MASK; // Bitmasking effect is hash %= HASHTABLE_SIZE
if (hashtable[hash].item == NULL) { // Free bucket
hashtable[hash].item = item;
hashtable[hash].count = 1;
break;
}
if (strcmp(hashtable[hash].item, item) == 0) { // Not hash collision; same item
hashtable[hash].count += 1;
break;
}
hash++; // Hash collision. Move to next bucket (linear probing)
if (hash == firsthash) {
// Table is full. This does not happen because the presizing is correct.
exit(1);
}
}
}