用于快速查找名称的容器

时间:2009-02-21 01:33:07

标签: c++ containers std

我想存储字符串并为每个字符串分配一个唯一的ID号(索引就可以了)。我只需要每个字符串的一个副本,我需要快速查找。我经常检查表中是否存在字符串,以至于我注意到了性能损失。什么是最适合使用的容器,如果字符串存在,我该如何查找?

8 个答案:

答案 0 :(得分:9)

我建议使用tr1 :: unordered_map。它被实现为散列映射,因此它具有用于查找的O(1)的预期复杂度以及O(n)的最坏情况。如果您的编译器不支持tr1,还有一个boost实现。

#include <string>
#include <iostream>
#include <tr1/unordered_map>

using namespace std;

int main()
{
    tr1::unordered_map<string, int> table;

    table["One"] = 1;
    table["Two"] = 2;

    cout << "find(\"One\") == " << boolalpha << (table.find("One") != table.end()) << endl; 
    cout << "find(\"Three\") == " << boolalpha << (table.find("Three") != table.end()) << endl; 

    return 0;
}

答案 1 :(得分:7)

试试这个:

alt text
(来源:adrinael.net

答案 2 :(得分:5)

尝试std :: map。

答案 3 :(得分:4)

首先您必须能够量化您的选择。您还告诉我们您感兴趣的主要使用模式是查找,而不是插入。

N为您希望在表格中使用的字符串数量,并让C为所述表格中任何给定字符串中的平均字符数(或者在根据表格检查的字符串中。

  1. 对于基于哈希的方法,对于每次查询,您需要支付以下费用:

    • O(C) - 计算您要查找的字符串的哈希值
    • 介于O(1 x C)O(N x C)之间,其中1..N是您希望基于散列密钥遍历存储桶的成本,此处乘以C以重新检查字符在每个字符串中对着查找键
    • 总时间:O(2 x C)O((N + 1) x C)
    • 之间
  2. 如果是基于 std::map的方法(使用红黑树),则每次查询都需要支付以下费用:

    • 总时间:在O(1 x C)O(log(N) x C)之间 - 其中O(log(N))是最大树遍历费用,O(C)std::map的通用时间less<>实现需要在树遍历期间重新检查查找键
  3. 如果N的值很大,并且没有散列函数可以保证少于log(N)的碰撞,或者你只是想安全地玩,你会更好使用基于树的(std::map)方法。如果N很小,一定要使用基于散列的方法(同时仍然确保哈希冲突很低。)

    在做出任何决定之前,您还应该检查:

答案 4 :(得分:2)

听起来像一个数组在索引是数组索引的地方就可以了。要检查它是否存在,只需确保索引位于数组的边界内,并且其条目不是NULL。

编辑:如果您对列表进行排序,您可以始终使用应该快速查找的二进制搜索。

编辑:此外,如果您要搜索字符串,也可以始终使用std::map<std::string, int>。这应该有一些不错的查找速度。

答案 5 :(得分:2)

是否可以静态搜索字符串?您可能希望查看perfect hashing function

答案 6 :(得分:1)

最简单的方法是使用std :: map。

它的工作原理如下:

#include <map>
using namespace std;

...

   map<string, int> myContainer;
   myContainer["foo"] = 5; // map string "foo" to id 5
   // Now check if "foo" has been added to the container:
   if (myContainer.find("foo") != myContainer.end())
   {
       // Yes!
       cout << "The ID of foo is " << myContainer["foo"];
   }
   // Let's get "foo" out of it
   myContainer.erase("foo")

答案 7 :(得分:0)