检查一个点是否已经在向量/列表中 - 性能

时间:2010-02-20 13:05:02

标签: c++ performance

这与this question

有关

我有一个点矢量,例如,存储100K +点。

std::vector<Point> point_vec; 

我想检查要添加的位置(x,y,z)是否已经在point_vec中(由class Point的实例表示)。以下函数将检查此项(在for循环中)

bool samePoints(const Point& p1, 
                const double x1, 
                const double y1, 
                const double z1) {

     return fabs(p1.x - x1) < EPSILON &&
            fabs(p1.y - y1) < EPSILON &&
            fabs(p1.z - z1) < EPSILON;
}

但是,我想检查x in list/ vector是否会成本高昂。我想知道是否有更好的方法来检查a)点是否相等(可能是类Point上的运算符“=”和(b)我应该制作一些比“vector”更好的数据结构吗?使用。或者如果对向量有一个操作,将加速检查“相同点”

对于(b)请注意我需要std ::对这些点进行排序。因此,您可能建议的任何其他数据结构应该能够对这些点进行排序。

更新

我只想要处于排序状态的点。只是向量不对它们进行排序(所以我需要执行排序操作。我应该使用std::set<Point> point_set而不是std::vector <Point> point_vec吗?如果这样:将每个点添加到一个集合中是昂贵的操作?或者我最后做的'矢量'排序结果总体上更昂贵?

4 个答案:

答案 0 :(得分:2)

点的集合是否总是排序或者有时必须处于未排序的状态?如果是前者,则std :;一组点将快速确定一个点是否已存在,并将按排序顺序维持点。您必须提供合适的排序函数(不是相等的函数),这可能比您的相等测试更快。

答案 1 :(得分:1)

我担心,虽然尼尔和弗拉德有正确的想法,但他们遗漏了一个特别重要的细节:如果你想要的话,你不能用一维比较器合理地排序N维点只能在epsilon中正确而不是完全正确。

Patrick目前使用四/八叉树,但没有使用散列 - 散列隐式需要一个映射,其中3D中关闭的所有项必须在1D(沿着散列)附近映射,这是不可能的。

因此,假设您可以使用比较器(如

)线性排序

x1<x2 || (x1==x2 && (y1<y2 || (y1==y2 && z1<z2))

这是你需要做的:

  • 抓住你的向量并沿每个维度减去epsilon。二进制搜索该元素的索引(如果有的话)。拨打i0
  • 拿起你的矢量并在每个维度上添加epsilon。对该索引进行二进制搜索。拨打i1
  • i0i1之间线性搜索所有内容,以查看其中任何内容是否实际位于每个维度中的向量的epsilon内(不仅仅是在1D排序方向)

如果您的点是随机分布的,那么这将比构建oct-tree更快。如果你的点往往沿着线下降(例如x1 == x2,y1 = y2,对于许多z),那么这个方案通常会选择列表中的大块使用线性排序无法区分,你应该使用oct -tree快速搜索。

答案 2 :(得分:0)

std::set在内部对项目进行排序。您只需要提供比较功能。

答案 3 :(得分:0)

STL set或hash_set可能会有所帮助。 构建结构将比构建向量或列表慢,但查找点会更快。

或者,您也可以使用四叉树或八叉树。