我试图找出用于此问题的最佳数据结构。我正在使用键作为字符串来实现键值存储。这些值经常被添加,通常只会被查找1到2次。最初我使用std::map
,但我发现性能不理想,因为添加密钥和重新平衡红黑树的开销掩盖了搜索值的时间减少。目前我正在使用修改后的单个链表。它使用包含c字符串(const char *)的结构,以字节为单位的长度以及存储的值。当我想使用键找到一个值时,我遍历列表并比较键的大小,如果它们匹配,我使用memcmp来检查字符串是否相同。如果它们相同,我会返回值。我可以使用这种方法在std::map
上实现大约10倍的性能提升。但是,我需要将其效率提高2倍。对于这个问题,任何人都可以推荐更好的数据结构吗?
答案 0 :(得分:3)
std::vector
迭代比链接列表更快,push_back()
更快,因为大部分时间都不需要内存分配。
答案 1 :(得分:3)
在不了解实际问题的情况下很难找到快速解决方案。特别是,您的数据集有多大,存储的实际数据在哪里(存储在容器中还是其他地方?)。您需要在容器上执行哪些其他操作?你需要从容器中删除元素吗?
作为对其中一个问题的评论,您说明需要在std::unordered_map
中复制密钥...如果密钥已经存储在其他地方,我建议您使用地图,但要避免复制字符串。使用指针作为键,并使用自定义比较器取消引用并在结果中操作:
// Assuming that the data is stored in std::string somewhere else
struct custom_compare {
bool operator()( std::string* lhs, std::string* rhs ) const {
return lhs!=rhs && (lhs->size() < rhs->size() || lhs->compare( *rhs ) < 0);
}
};
std::map< std::string*, data, custom_compare > mymap;
通过存储指针而不是实际的字符串,这将消除复制。自定义比较器基本上与您在列表中实现的比较器一样快,树将平衡内容,允许O(log n)查找。根据集合的大小(如果有很多元素),这将是线性搜索的改进,而如果大小很小,那么线性搜索会更好。
此外,根据数据的多样性,您可能希望遵循线性搜索,但根据一些快速计算的标准划分搜索空间,同时尽可能均匀地划分集合。例如,您可以使用线性搜索,但不是保留单个列表,而是根据密钥长度保留不同的列表。
如果标准实际上是基于字符串的内容(字母,而不是大小),那么您将近似于特里结构的定义。如果你得到一个已经实现的库,或者你愿意花费所需的时间,那么trie可能是这种类型查找的最快容器之一,因为它会从“number”变换“size”变量元素到字符串的长度。
答案 2 :(得分:2)
您将其作为标签之一...为什么不使用Trie?插入应该很快,因字符重叠而导致内存使用率下降,并且查找速度很快。
答案 3 :(得分:0)
也许某种哈希表?对密钥使用良好的哈希算法可以大大加快搜索时间。你的插入时间会慢一些,但如果你的哈希函数是好的话,希望不是很多。