正在寻找C++不可变的hashset/hashmap

Looking for C++ immutable hashset/hashmap

本文关键字:hashset hashmap 不可变 寻找 C++      更新时间:2023-10-16

我用大量的数据处理来处理GPL'ed C++代码。我们经常使用的一种特殊模式是收集一定数量(数千到数百万(的键或键/值对(通常为int32.int128(,将它们插入hashset/hashmap,然后在不进行进一步修改的情况下使用它。

我将其命名为不可变哈希表,尽管单赋值哈希表可能是更好的名称,因为我们在完全构建之前不使用它。

今天我们使用的是STL unordereded_map/set,但我们正在寻找一个更好(尤其是更快(的库。你能推荐一些适合这种情况的、与GPL兼容的许可证吗?

我认为最有效的方法是根据bucket num对所有密钥进行基数排序,并提供bucket->range映射,因此我们可以使用以下代码来搜索密钥:

bool contains (set,key) {
h = hash(key);
b = h % BUCKETS;
for (i : range(set.bucket[b], set.bucket[b+1]-1)
if (set.keys[i]==key)  return true;
return false;
}

你对这种方法有什么看法?你能提出一种更快的方法来实现不可变的映射/集吗?

我认为,对于您的情况,Double Hashing或Robin Hood Hashing更合适。在许多可能的算法中,我更喜欢使用带有2^n表和奇数步的双哈希。这种算法非常高效且易于编码。以下只是uint32_t密钥的容器示例:

class uint32_DH {
static const int _TABSZ = 1 << 20; // 1M cells, 2^N size
public:
uint32_DH() { bzero(_data, sizeof(_data)); }
bool search(uint32_t key) { return *lookup(key) == key; }
void insert(uint32_t key) { *lookup(key) = key; }
private:
uint32_t* lookup(uint32_t key) {
uint32_t pos  = key + (key >> 32) * 7919;
uint32_t step = (key * 7717 ^ (pos >> 16)) | 1;
uint32_t *rc;
do {
rc = _data + ((pos += step) & (_TABSZ - 1)); 
} while(*rc != 0 && *rc != key);
return rc;
}
uint32_t _data[_TABSZ]; 
}