【问题标题】:Which data structure should I use我应该使用哪种数据结构
【发布时间】:2011-02-10 18:27:04
【问题描述】:

我正在尝试找出解决此问题的最佳数据结构。我正在使用字符串键实现键值存储。这些值经常被添加,通常只会被查找 1 或 2 次。最初我使用std::map,但我发现性能并不理想,因为添加键和重新平衡红黑树的开销超过了搜索值的时间减少。目前我正在使用修改后的单链表。它使用一个包含 c 字符串 (const char *)、字节长度和存储值的结构。当我想使用键查找值时,我遍历列表并比较键的大小,如果它们匹配,我使用 memcmp 检查字符串是否相同。如果它们相同,则返回该值。与std::map 相比,我使用这种方法可以获得大约 10 倍的性能。但是,我需要将其效率提高约 2 倍。对于这个问题,谁能推荐一种更好的数据结构类型?

【问题讨论】:

  • 有多少元素?键的平均大小是多少?

标签: c++ data-structures tree trie


【解决方案1】:

如果不了解实际问题,很难找到快速解决方案。特别是,您的数据集有多大,真实数据存储在哪里(是存储在容器中还是其他地方?)。您还需要对容器执行哪些其他操作?需要从容器中删除元素吗?

作为对其他问题之一的评论,您声明需要将密钥复制到 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 的定义。如果你得到一个已经实现的库,或者你愿意花时间这样做,那么 trie 可能是这种查找最快的容器之一,因为它将“大小”变量从数量元素到字符串的长度。

【讨论】:

  • 谢谢。我不知道您可以在 std::map 中使用自定义比较器。
【解决方案2】:

std::vector 的迭代速度应该比链表更快,push_back() 的迭代速度也更快,因为大多数时候不需要内存分配。

【讨论】:

    【解决方案3】:

    您将它作为您的标签之一...为什么不使用Trie?插入应该很快,由于字符重叠,内存使用率会下降,并且查找速度很快。

    【讨论】:

      【解决方案4】:

      也许是某种哈希表?为您的密钥使用良好的散列算法将大大加快您的搜索时间。您的插入时间会稍微变慢,但如果您的哈希函数很好,希望不会很慢。

      【讨论】:

      • @RTS:用std::unordered_map(哈希表)替换std::map(rbtree)并进行测试应该相当容易。我对代码中的std::unordered_map 性能非常满意。
      • @Blastfurnance:我已经尝试过 std::unordered_map 和 std::tr1::unordered_map,在我的用例中,它们比我的链表解决方案要慢。由于他们需要键数据的副本,而使用链表,我可以只复制字符串指针。
      猜你喜欢
      • 2013-07-14
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 2012-04-24
      • 1970-01-01
      相关资源
      最近更新 更多