我想知道最有效的方法是什么。
我有点从两个地方收集。
我只对这两个地方共有的要点感兴趣。
我的计划是有3 std::set<Point>
。首先,我将从区域A添加点到集合A,然后从B点到集合B,让集合C成为两个集合的交集。
但是,我想知道是否有更好的方法可以做到这一点,可能涉及更少的设置?
由于
答案 0 :(得分:4)
你的问题很常见,甚至有一种(以明显的方式命名)standard algorithm set_intersection()
供你使用。
答案 1 :(得分:1)
你可以取消集合B:首先从A收集点到集合A,然后从B收集点,但只有当它们也存在于A中时才将它们放入C.
如果A组和B组的大小不同(且可预测),那么明显的选择就是消除较大的大小。
答案 2 :(得分:1)
天真的基于集合的方法(构建两个集合,然后生成交集),具有以下步骤:
std::set A
1.说源1有N个点,这是:
std::set B
。假设这有M分,给出:
std::set_intersection
略有改进的基于集合的方法是:
std::set
A(与上面相同的复杂性)对于第二个来源中的每个点,如果(并且仅当)它在集合A中,则将其添加到结果中
您可以使用std::set
执行此操作,如下所示:
if (a.find(point) != a.end())
result.insert(point);
请注意,如果您知道哪个点源将提供更少的点,则应使用该源构建集A以获得最佳性能。如果您的来源按排序顺序提供点数,您可以完全避免这些集合并节省更多空间和空间。时间。
答案 3 :(得分:0)
您可以map<Point, int>
将每个点映射到它出现的次数,即1或2.然后删除仅出现一次的所有点。
答案 4 :(得分:0)
您可以使用map<Point,int>
存储发生1或2次的点数。在这种情况下,您还必须重载<
运算符。
答案 5 :(得分:0)
我认为使用三组和std :: set_intersection的方法是最合乎逻辑和最有效的。虽然如果你真的想拥有更少的集合,你可以迭代集合B并删除不在A中的点然后迭代集合A并删除不在B中的点。这应该这样做。
答案 6 :(得分:0)
如果您在点上定义词典operator<
,即(如果需要,推断&gt; 2维)
bool operator<(Point const &a, Point const &b)
{
if (a.x != b.x) return a.x < b.x;
return a.y < b.y;
}
然后std::set
可能具有足够好的性能来有效地计算交叉点。假设您的两个组已经在数组中,或者在运行中生成,则需要2组:
A = { all points from A }
C = { }
for all points in B:
if point is in A:
add point to C
如果您使用浮点坐标,那么您可能需要允许浮点错误并搜索A
中<{1>} 附近的所有点{{1} }。然后,您需要一个空间分区结构,例如k-d tree或quadtree/octree。这将涉及引入一个新的库或编写一个相当复杂的数据结构,所以如果可能的话我会避免它。