C++ 大向量搜索项

Posted

技术标签:

【中文标题】C++ 大向量搜索项【英文标题】:C++ Big vector search item 【发布时间】:2012-11-17 19:38:39 【问题描述】:

第一次在这里发帖,这让我发疯了!我解释的不是很清楚,所以我试着举个例子。

我正在尝试检索一个非常大 (100k) 向量中的元素以将其擦除。迭代槽需要很长时间......所以我尝试了这个:

这是我列表中的一个小例子。它存储在我的单例粒子发射器类中。

vector<Particle> particles;
particles.reserve(100);

这是我的粒子的精简版

class Particle

Particle:
~Particle:

void Delete

  int listNum = (this - &particles[0]);
  particles.erase(particles.begin+listNum);

;

这一切都很好,但我不想将每个粒子都保存在堆栈中,所以我想更改它

vector<Particle> particles;

进入

vector<Particle*> particles;

现在我的问题是:如果向量由粒子指针组成,是否仍然可以从列表中删除和擦除粒子?

我不确定我是否清楚我的问题,但我希望你能理解!

或者,如果有人知道更好的性能明智的解决方案,我想听听!

提前致谢!

【问题讨论】:

你的 Particle 类不应该知道是什么容器保存它。 粒子有多大?如果复制构造很昂贵,那么您应该存储为指针,但使用指针容器(例如boost::ptr_vector),我同意克里斯,将容器知识灌输到类不是一个好主意...... 另外,为了减少搜索时间,你可以有一个排序的向量吗? “但我不想将每个粒子都保存在堆栈中”std::vector 的存储在堆上。 @chris:一般来说建议不错,但有时出于性能原因,您需要偏离最佳实践。 【参考方案1】:

你打算如何使用这个std::vector

您说迭代需要很长时间,但如果您的目标是迭代所有值,那么您根本无法比连续数组做得更好。您谈到从容器中删除元素,这表明您需要一个动态数组,这正是std::vector 的含义。

无论如何,您绝对不想存储原始指针向量。如果您测量并发现由于使用某些操作而导致性能不足,您的两个选项应该是 std::vector&lt;Particle&gt;(通常首选)或 std::vector&lt;unique_ptr&lt;Particle&gt;&gt;(仅限 C++11)。根据您的用例,std::map&lt;Particle&gt;std::set&lt;Particle&gt; 可能是个好主意,但我们没有足够的信息。

您没有在堆栈上存储任何Particlestd::vector 中的每个元素都已经在空闲存储区(“堆”)中。

您的插入和删除代码也应该与您的Particle 类无关。插入和删除是对容器的操作,而不是对包含的元素的操作。

要回答您的问题,我们需要了解一些事情。

首先,Particle 有多大?这可能是最重要的信息。

其次,你用容器做什么?您通常是在查看每个 Particle 并与它们一起做事,还是在整个容器中搜索特定的 Particle?如果您正在搜索,您是否尝试根据某种键进行查找(例如,每个 Particle 都有一个唯一 ID,并且您在该 ID 上查找整个 Particle),或者您正在查找如果一个Particle 匹配另一个(也就是说,您根据Particle 的身份进行查找)?

如果您正在查找个人Particle,那么std::set 应该是您使用方便的首选,因为它允许进行二分搜索。如果您的用例让您按键搜索粒子,那么您需要std::map&lt;Key, Particle&gt;

如果你有一堆粒子,并且你想从容器中删除一些,那么对象的大小就很重要了。但是,在这种情况下,您通常需要std::vector

简而言之,我需要更多信息才能完整回答您的问题。

【讨论】:

好的,谢谢你的信息,我会先处理你的建议,看看我能不能从中做点什么!【参考方案2】:

如果您担心将向量放入堆栈,为什么不尝试这样的事情:

vector <Particle> * particles = new vector <Particle>;

这将使向量持续到您delete 它。此外,如果您担心性能问题,set 将是一个好主意。这保证了所有插入和删除都是对数时间,并且您不必使用自己的删除函数。要在 C++11 中获得更好的性能,请尝试 unordered_set

【讨论】:

std::vector 已经在堆上分配。你的改变并没有真正完成任何事情。 刚刚意识到这一点。然而,由于他似乎是在一个函数中声明它,所以如果有必要,只要他需要,执行 new/delete 方法将保留它。 根据需要保留它无论如何都应该有效,特别是对于 C++11 移动语义。此外,OP 显然将其声明为 globally,这很可怕,但绝对不需要复制/移动。 哈哈,不是全局的,但我把它放在我的粒子发射器类中 存储指向 std::vector 而不是 std::vector 本身的指针并没有真正的优势。 std::vector 通常在堆栈上分配 sizeof(pointer) * 3,而不管 std::vector 中包含多少元素。

以上是关于C++ 大向量搜索项的主要内容,如果未能解决你的问题,请参考以下文章

C++:如何检测向量中的重复项并打印一份?

涉及向量的二分搜索问题 (C++)

在 C++ 中初始化非常大的向量

如何在 C++ 中比较两个大向量的大小

如何在 C++ 中的矩阵中搜索向量以及哪种算法?

具有最快“存在”搜索的 C++ 容器(向量/数组/等)