【问题标题】:Suitable Data Structure for storing and calculating Highest Scoring K items适合存储和计算最高得分 K 项的数据结构
【发布时间】:2011-02-21 20:51:30
【问题描述】:

我需要存储 W 个项目。每个项目都有一个“字符串”属性和一个与之关联的“双”属性(项目的分数)。在每次迭代中,额外的 C 项被添加到集合中。迭代完成后,一些项目的分数会有少量更新。现在,在 W+C 项中,只有 W 项需要进行下一次迭代。将选择得分最高的“W”项目,这些项目将传给下一代。 在每次迭代中,都会添加一组不同的“C”项。

W 约为 10,000。 C 的数量级为 600。

就时间复杂度而言,使用它的最佳数据结构是什么。哈希表、堆、二叉搜索树?? 我正在使用 C++。一些提升参考将不胜感激

【问题讨论】:

  • 更新的本质是什么“迭代完成后,部分item的score有少量更新。”?您会以某种方式搜索这些元素还是只是线性扫描?
  • 从一个单独的模块中,我获得了哪些项目(由字符串属性标识)需要更新其分数的信息。更具体地说,从另一个模块获取当前迭代中使用的项目的信息并更新它们的分数(分数代表使用频率)。 'C' 最不常用的物品被扔掉。
  • 这是用于遗传算法实现吗?
  • @Emile - 它不完全是遗传算法(但结构与遗传算法相同),我可以看到在遗传算法实施中需要同样的东西。

标签: c++ sorting data-structures hashtable


【解决方案1】:

我会将这些值存储在两个并行结构中。首先,有一个双精度值数组,每个值都存储一个指针。接下来,将所有字符串与辅助整数一起存储在哈希表中。这个想法是,数组中的指针指向哈希表中的节点或保存与双精度相关联的字符串的特里树,而每个字符串的整数值存储与该字符串配对的双精度的索引。

要将字符串/双精度对插入此结构,请将字符串添加到哈希表,将双精度附加到数组,然后在数组中存储指向新字符串的指针以及哈希中双精度的索引桌子。这具有 O(k) 的复杂度,其中 k 是字符串的长度。

要更改优先级,请在哈希表中查找字符串,然后获取数组中双精度数的索引。然后,您可以修改该元素以更改关联的优先级。这也有复杂度 O(k)。

要丢弃除前 B 个键/值对之外的所有键/值对,请对数组运行选择算法,将前 B 个元素放在数组的一部分中,将剩余的 C 元素放在另一部分中。每当您执行交换时,请按照数组中的指针进入哈希表并更新刚刚交换的元素的索引。最后,遍历数组的最后一个 C 元素,按照它们的指针返回哈希表,并从表中删除它们指向的元素。这需要 O(n) 时间来执行选择步骤,或者最坏情况下使用中位数算法的 O(n) 时间,然后是 O(n) 时间从哈希表中删除元素,对于O(n) 的预期运行时间,其中 n 是结构中元素的数量。

总而言之,这使您可以 O(k) 插入和查找任何字符串,其中 k 是字符串长度,并且 O(n) 保留最佳元素,其中 n 是元素的总数。

【讨论】:

  • 感谢您的好评!你认为 std::nth_element 的性能会和我自己的中位数算法或快速选择一样好吗??
  • @Akhil- 据我所知,nth_element 应该可以用于此目的。它可能是使用 quickselect 或 introselect 实现的(一种快速选择变体,当它看起来正在退化时,它会依赖于中位数的中位数)。我建议不要实现你自己的,除非它看起来像 nth_element 不够快。
【解决方案2】:

好吧,我认为您只需在迭代结束时使用std::vector<Item> 并执行std::nth_element(得分)一次就可以了。例如。如果您想保留 10000 个项目,请这样做:

struct Item {
    double score;
    std::string name;
};

bool comparator(const Item& a, const Item& b) {
    return a.score > b.score;
};

if (items.size() > 10000) {
   // Make sure the 10,000 first elements contain the highest scores.
   items.nth_element(item.begin(), item.begin() + 10000, item.end(),
       comparator);
   // Only keep the first 10,000 elements.
   items.resize(10000);
}

实际上,如果您这样做,更新值(通过线性搜索和字符串比较)可能会比排序慢。您可以通过将字符串散列放入 Item 而不是纯字符串来加快比较速度。

如果您想要更快的更新:在更新之前,按字符串哈希对项目进行排序。然后你可以做一个二分搜索而不是线性搜索来找到你想要更新的项目。

【讨论】:

  • std::nth_element() 的复杂度是多少?我查看了stl_algo.h,但它太复杂了,无法在短时间内理解。减少更新时间的一种方法是维护一个关联的哈希表,其中包含指向各个向量索引的指针。这可以在 O(n) 时间内完成。从 templatetypedef 的回复中购买的想法
猜你喜欢
  • 2017-03-16
  • 2010-12-29
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2018-09-03
  • 2011-05-09
相关资源
最近更新 更多