【问题标题】:Fastest way to find a vector in a vector of vectors在向量向量中找到向量的最快方法
【发布时间】:2015-04-24 06:04:10
【问题描述】:

我的代码是:

struct TileIdx { int mRow; int mCol; };

typedef std::vector<TileIdx> TileChain;

bool IsChainInChains(const TileChain& chain, const std::vector<TileChain>& chainArray);

分析器显示IsChainInChains 是我的代码的瓶颈。
我需要最快的方法来实现这个功能。
我们可以假设,chainArray 已经排序(哪种方式?由您决定)。
我们还可以假设 mRow 和 mCol 不会超过 100(即,mRow * 100 + mCol 是用于排序目的的有效 int)。
我不是故意将我当前的实现包括在内,以便社区不仅分析我的代码,而且提出新的解决方案。

【问题讨论】:

  • 因无缘无故未能提供当前解决方案而减 1。这会让你的问题变得更糟。
  • @Yakk 我解释了我的原因。我不只是希望分析我的代码,而是寻找不同的方法。这样问题就更常见了,因此对未来的社区更有用。

标签: c++ vector stl stdvector


【解决方案1】:

在没有太多有用信息的情况下,我建议使用二进制搜索。为此,请使用标准库函数std::lower_bound

auto it = std::lower_bound(begin(chainArray), end(chainArray), chain, comp);

其中comp 是用于排序chainArray 的谓词,并且是严格的弱排序

请注意,std::vector 有一个 operator&lt;,它执行其元素的字典比较。如果使用三个参数调用,这将被 std::lower_bound 使用。因此,如果您将bool operator&lt;(TileIdx, TileIdx) 实现为严格的弱排序,则可以省略comp 的使用:

bool operator<(TileIdx rhs, TileIdx lhs) { .... }

std::sort(begin(chainArray), end(chainArray));

....

auto it = std::lower_bound(begin(chainArray), end(chainArray), chain);

【讨论】:

  • 请说明问题中没有哪些有用信息。
  • @deko 我们不知道您是否在使用二分搜索。我们不知道您是否已经在使用std::loser_bound。无法知道为什么您的实施“缓慢”。也许没有办法加快速度。
  • 我明白你的意思。我不使用std::lower_bound。我试试你的方法!谢谢!
【解决方案2】:

你真的需要向量的向量吗?如果您对数据的其他操作可能较慢,那么使用一组向量是一个好主意。看这个小例子:

#include <set>
#include <vector>

struct TileIdx { int mRow; int mCol; };

typedef std::vector<TileIdx> TileChain;

bool operator < (const TileChain& t1, const TileChain& t2)
{
  if(t1.size() < t2.size())
    return true;
  if(t1.size() > t2.size())
    return false;
  for(unsigned long int i = 0; i < t1.size(); ++i)
  {
    if(t1[i].mRow < t2[i].mRow)
      return true;
    if(t1[i].mRow > t2[i].mRow)
      return false;
  }
  return false;
}

bool IsChainInChains(const TileChain& chain, const std::set<TileChain>& chains)
{
  return chains.count(chain) > 0;
}

然后,您必须根据您的目标选择容器。供您参考,这些操作所需的时间是:

  • 在 Chains 中插入一个新链需要 O(log(n)) 用于 set,O(1) 用于 vector
  • 在 Chains 中查找链需要 O(log(n)) 用于 set,O(n) 用于 vector
  • set 中已经对Chains 中的链进行排序,vector 需要 O(n*log(n))

那么,如您所见,如果您不经常修改Chains,但经常在其中检查,std::set 是一个很好的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    相关资源
    最近更新 更多