【发布时间】:2009-02-21 01:33:06
【问题描述】:
我想存储字符串并为每个字符串分配一个唯一的 ID 号(索引就可以了)。我只需要每个字符串的一份副本,并且需要快速查找。我经常检查表中是否存在字符串,以至于我注意到性能下降。什么是最好的容器,如果字符串存在,我如何查找?
【问题讨论】:
标签: c++ containers std
我想存储字符串并为每个字符串分配一个唯一的 ID 号(索引就可以了)。我只需要每个字符串的一份副本,并且需要快速查找。我经常检查表中是否存在字符串,以至于我注意到性能下降。什么是最好的容器,如果字符串存在,我如何查找?
【问题讨论】:
标签: c++ containers std
我建议使用 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;
}
【讨论】:
试试这个:
(来源:adrinael.net)
【讨论】:
试试 std::map。
【讨论】:
首先您必须能够量化您的选择。您还告诉我们,您感兴趣的主要使用模式是查找,而不是插入。
让N 是您希望在表中包含的字符串数,并让C 是所述表中存在的任何给定字符串(或字符串中)的平均字符数对照表进行检查)。
在基于散列的方法的情况下,对于每次查找,您需要支付以下费用:
O(C) - 计算您要查找的字符串的哈希值O(1 x C) 和O(N x C) 之间,其中1..N 是您期望基于哈希键遍历存储桶的成本,这里乘以C 以根据查找键重新检查每个字符串中的字符
O(2 x C)和O((N + 1) x C)之间
在 std::map-based 方法(使用红黑树)的情况下,您为每次查找支付以下费用:
O(1 x C) 和O(log(N) x C) 之间 - 其中O(log(N)) 是最大树遍历成本,O(C) 是std::map 的通用less<> 实现重新检查查找键所需的时间在树遍历期间如果N 的值很大,并且没有保证小于 log(N) 冲突的哈希函数,或者如果你只是想安全地玩,你最好使用基于树的 (std::map) 方法。如果 N 很小,请务必使用基于哈希的方法(同时仍确保哈希冲突较低。)
不过,在做出任何决定之前,您还应该检查:
【讨论】:
要搜索的字符串是静态可用的吗?你可能想看看perfect hashing function
【讨论】:
听起来像一个数组可以正常工作,其中索引是数组的索引。要检查它是否存在,只需确保索引在数组的范围内并且其条目不为 NULL。
编辑:如果您对列表进行排序,您始终可以使用应该具有快速查找的二进制搜索。
编辑:另外,如果你想搜索一个字符串,你也可以随时使用std::map<std::string, int>。这应该有一些不错的查找速度。
【讨论】:
最简单的方法是使用 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")
【讨论】:
【讨论】: