我应该在我的特殊情况下使用矢量还是设置?还是完全不同的东西?

时间:2013-10-25 08:40:25

标签: c++ sorting boost stl containers

所以,我花了很多时间阅读各种问题,博客文章,文章等关于不同情况下不同STL容器的性能比较。

但是,我还没有找到我的确切情况(3D游戏)的良好来源:

我正在收集大量(绝对超过5k,可能低于50k)指向某个类的指针(它的确切性质与我认为不相关)并且想要通过单个浮点值对它们进行排序,这决定了它们与某些类的距离任意位置(在帧期间不会改变)。

之后,我想迭代每个存储的指针。订单在这里很重要,因此排序。

以下是伪代码的情况:

// A: Insertion
foreach (class instance that needs sorting):
    container.insert( pair(distanceOfInstance, instance) );

// B: Sorting - using the distanceOfInstance as the determining factor
container.sort();

// C: Iteration in sorted order
foreach (pair in container)
    doSomethingWith(pair.instance);

整个过程(可能)在游戏中的每一帧重复,因此这里的最佳表现有点重要。必须在每次 A 之前清除容器。在 C 之后,没有其他任何操作。

我不做(我重复,不)需要:

  • 随机访问容器。
  • 在对容器进行排序后插入新元素的能力。

目前,我认为最快的是使用矢量或集合。但我不知道 - 在我的情况下 - 将元素插入向量,然后对其进行排序,然后迭代每个元素一次会更快。或者,如果将元素插入集合中更快(从而在插入期间对它们进行排序),然后迭代每个元素一次。

我们还在我们的项目中使用boost来完成其他任务,所以如果有人知道更好的解决方案内部提升(或完全不同的话),我会非常乐于接受建议。此外,对不起,如果这个问题已经得到解答,我只是没有找到它:)

5 个答案:

答案 0 :(得分:2)

在实践中,向量几乎总是更快;如果您不需要使用查找交换更新,那么没有理由 1 就可以使用set

也就是说,您还可以查看Google的B-tree实施,该实施应该比设置更快。


1 也就是说,除非您还要检查并删除重复项,否则会有多个重复项。
(这不常见。)

答案 1 :(得分:1)

如果您只需要对元素进行排序,我认为如果使用向量,您将获得更好的性能。你也可以考虑使用一个列表,虽然我认为它会比一个矢量稍慢。

答案 2 :(得分:1)

性能总是很棘手:你应该以两种方式实现它并测量哪一种能提供更好的输出。

那就是说,如果在创建时保留足够的元素,我认为向量会更好:如果你使用set,新插入的元素将在每次插入时被分类到集合中。使用矢量,您只需支付一次该费用。

答案 3 :(得分:1)

正如其他答案所述,应在您的情况下使用矢量。关于时间复杂度,对向量进行排序需要时间 O(n log n)其中 n 是您插入的元素数。对于std::set,已经排序的序列以每次插入的 O(log n)为代价。插入 n 元素也会导致 O(n log n)运行时间。但是由于更好的内存局部性,矢量解决方案会更快(简而言之,它存储在一个连续的内存范围内,可以快速读写)。

此外,std::vector仅具有恒定的空间开销,而std::set具有线性开销(通常实现为Rb-tree)。

如果你有很多次迭代并且 n 是一个很大的数字,请避免在每次迭代中分配向量的内存。而不是

while (true) {
  vector<YourClass*> container;
  container.reserve(numInstancesInCurrentIteration);
  // your code, insertions with 'container.emplace_back(...)'
}

做类似的事情:

vector<pair<float, YourClass*> > container;
while (true) {
  if (container.size() < numInstancesInCurrentIteration)
    container.resize(numInstances, pair<float, YourClass*>(-1.f, NULL));

  // A: Insert using assignments
  size_t pos = 0;
  foreach (class instance that needs sorting):  // pseudo-code
    container[pos++] = make_pair(distanceOfInstance, &instance);

  // B: Sort only the used range
  std::sort(container.begin(), container.begin() + pos);

  // C: Iterate over pointers sorted by distance
  for (auto it = container.begin(); it != container.begin() + pos; ++it)
    doSomethingWith(it->second);
}

经过一些迭代后,对container.resize()的调用将变得非常罕见。 doSomethingWith(YourClass*)的来电可能会成为您计划中最昂贵的部分。

答案 4 :(得分:0)

正如其他人回答的那样,我也会选择矢量。它更简单,可以更好地访问对象的内存布局。