map或hashmap有效查找泛型字符串?

时间:2012-08-14 17:59:28

标签: c++ string hash dictionary unordered-set

我需要能够存储和查找通用字符串。我不太了解字符串的内容,稍多于2/3的是人类语言单词,其余的更接近UUID或数字/字母组合。我知道任何特定的分组都是不变的(即如果它有一些人类的话,它将是所有人类的话,如果它有一些UUID,所有的内容都将是UUID等)。

我需要决定是否应将此数据放在地图或散列图中以获得最佳平均查找率。我倾向于用O(log n)运行时说地图,因为当我对输入格式知之甚少时,我不相信我能为字符串做一个合适的高效哈希。有什么想更好的想法?

编辑: 我忘记了一个关键方面。我不知道字符串的长度,所以我担心长字符串的内存使用量可能会变得过大。如果我使用哈希方法,我会做一些事情,在X字符之后哈希不按每个字符散列,以避免内存消耗太大。

我真正想要的是一个哈希映射实现,它将“桶”中的多组值保存在有序的管理器中,以便它可以提供对桶的(log N)搜索;但我不认为stardrd C ++中存在这种情况,并且不值得从头开始编写。

PPS。数据接近静态。我偶尔要添加到列表中这是罕见的,我愿意接受一个缓慢的写入时间。我只关心查找时间。

4 个答案:

答案 0 :(得分:4)

很难提出一个建议。它取决于几种权衡(迭代类型,内存与查找)。在整个我假设您可以使用C ++ 11编译器(或等效的Boost或TR1库)。

如果插入/查找时间对您来说最重要,我肯定会将std::unordered_set(请参阅reference)与std::hash<std::string>一起使用(请参阅{{ 3}})。 referenceinsertion平均O(1)(摊销常数)。如果

请注意,无序哈希容器不允许您按排序顺序进行迭代。因此,如果您想要排序迭代,那么您可以使用订购的容器std::set<std::string>,但您支付的价格是O(log N)查找/插入。

内存限制更难以分析。首先,有序容器std::setstd::map每个元素开销需要大约 3个字,以维护允许有序迭代的树结构。然而,无序散列容器具有一些备用容量,因为散列容器在满载因子上运行得非常差。

#include <iostream>
#include <functional>
#include <string>
#include <unordered_set> // or <set> for ordered lookup

int main()
{
    // or std::set<std::string> for ordered lookup
    std::unordered_set<std::string> dictionary; 

    std::string str = "Meet the new boss...";
    dictionary.insert(str);
    auto it = dictionary.find(str);

    std::cout << *it << '\n';
}

lookup上的输出。如果您还希望将Valuestd::string一起存储,则可以使用具有相同哈希函数的std::unordered_map<std::string, Value>std::map<std::string, Value>

结论:最好根据上述权衡来衡量哪种方法最适合您的应用。

答案 1 :(得分:3)

除了std :: set,std :: map,std :: unordered_set和std :: unordered_map之外 - 我还会考虑学习尝试,看看它们是否更合适:

http://en.wikipedia.org/wiki/Trie

答案 2 :(得分:1)

CedarHAT-TrieJudyArray非常棒,您可以找到基准here

benchmark result

答案 3 :(得分:0)

您可能想要查看基准测试:http://www.dotnetperls.com/sorteddictionary 它出现在实际应用中,尽管有冲突,但Dictionary优于SortedDictionary。