【发布时间】:2009-01-26 14:16:42
【问题描述】:
我有一个包含大约数百个 C++ 唯一字符串的列表,我需要检查该列表中是否存在某个值,但最好快如闪电。
我目前正在使用带有 std::strings 的 hash_set(因为我无法让它与 const char* 一起使用),如下所示:
stdext::hash_set<const std::string> _items;
_items.insert("LONG_NAME_A_WITH_SOMETHING");
_items.insert("LONG_NAME_A_WITH_SOMETHING_ELSE");
_items.insert("SHORTER_NAME");
_items.insert("SHORTER_NAME_SPECIAL");
stdext::hash_set<const std::string>::const_iterator it = _items.find( "SHORTER_NAME" ) );
if( it != _items.end() ) {
std::cout << "item exists" << std::endl;
}
在不自己构建完整哈希表的情况下,是否有其他人对更快的搜索方法有一个好主意?
列表是一个固定的字符串列表,不会改变。它包含受特定错误影响的元素名称列表,当使用较新版本打开时应立即修复。
我在使用 Aho-Corasick 之前已经构建了哈希表,但我不太愿意添加太多复杂性。
我对答案的数量感到惊讶。我最终测试了一些方法来测试它们的性能,最后结合了 kirkus 和 Rob K. 的答案。我之前尝试过二进制搜索,但我想我有一个小错误来实现它(它有多难......)。
结果令人震惊...我以为我使用 hash_set 进行了快速实现...好吧,结果我没有。以下是一些统计数据(以及最终代码):
随机查找 5 个现有密钥和 1 个不存在密钥,50.000 次
我的原始算法平均耗时 18,62 秒
线性搜索平均需要 2.49 秒
二进制搜索平均需要 0,92 秒。
使用 gperf 生成的完美哈希表进行搜索平均需要 0,51 秒。
这是我现在使用的代码:
bool searchWithBinaryLookup(const std::string& strKey) {
static const char arrItems[][NUM_ITEMS] = { /* list of items */ };
/* Binary lookup */
int low, mid, high;
low = 0;
high = NUM_ITEMS;
while( low < high ) {
mid = (low + high) / 2;
if(arrAffectedSymbols[mid] > strKey) {
high = mid;
}
else if(arrAffectedSymbols[mid] < strKey) {
low = mid + 1;
}
else {
return true;
}
}
return false;
}
注意:这是 Microsoft VC++,所以我没有使用 SGI 的 std::hash_set。
我今天早上按照VardhanDotNet 的建议使用 gperf 进行了一些测试,这确实快了很多。
【问题讨论】:
标签: c++ visual-c++