我编写了以下程序,该程序从XYZ点列表(相应的列2 3和4)中提取给定距离和给定高度差的点对。问题是它包含一个嵌套的for循环,我认为这会引起太多的迭代,因此对于大量的点(> 1000),例程需要一个不合理的时间来完成。如何优化此算法?
此致
胺
Sub Test1()
Columns("H:K").Select
Selection.ClearContents
c3 = 2
For c2 = 2 To 10
For c1 = c2 + 1 To 10
If Sqr((Cells(c2, 2) - Cells(c1, 2)) ^ 2 + (Cells(c2, 3) - Cells(c1, 3)) ^ 2) = 1 Then
If Abs(Cells(c1, 4) - Cells(c2, 4)) = 10 Then
Cells(c3, 8) = Cells(c1, 2)
Cells(c3, 9) = Cells(c1, 3)
Cells(c3, 10) = Cells(c2, 2)
Cells(c3, 11) = Cells(c2, 3)
c3 = c3 + 1
End If
End If
Next c1
Next c2
End Sub
答案 0 :(得分:1)
鉴于您需要评估每个点之间的距离和高度,您没有很多选项来优化算法。
你可以像Vikram Bhat那样说并在3d树中对你的数据进行排序,但这意味着花费计算时间来构建树,如果你只使用树,我不确定你会获得很多时间。
您可以通过删除Sqr()来更快地评估距离
((x2-x1)²+(y2-y1)²)=(距离)²
由于您正在寻找固定距离,因此计算(距离)²的速度会更快一次,然后使用每个if中的值。
在您的情况下(距离= 1,然后距离²= 1),您的测试将变为:
((Cells(c2, 2) - Cells(c1, 2)) ^ 2 + (Cells(c2, 3) - Cells(c1, 3)) ^ 2) = 1
您还可以使用距离近似算法:
http://en.wikibooks.org/wiki/Algorithms/Distance_approximations
如果条件检查距离之前的高程,则另一个优化是交换两个。因为这个条件计算速度更快,并且可以避免计算距离,所以它可能是您的算法的一个很好的加速。
您的代码已修改:
Sub Test1()
Columns("H:K").Select
Selection.ClearContents
c3 = 2
For c2 = 2 To 10
For c1 = c2 + 1 To 10
If ((Cells(c2, 2) - Cells(c1, 2)) ^ 2 + (Cells(c2, 3) - Cells(c1, 3)) ^ 2) = 1 Then
If Abs(Cells(c1, 4) - Cells(c2, 4)) = 10 Then
Cells(c3, 8) = Cells(c1, 2)
Cells(c3, 9) = Cells(c1, 3)
Cells(c3, 10) = Cells(c2, 2)
Cells(c3, 11) = Cells(c2, 3)
c3 = c3 + 1
End If
End If
Next c1
Next c2
End Sub
答案 1 :(得分:0)
您应该考虑使用3d-tree帮助获取O(logn+k) where k are valid neighbours
中的最近邻居,如果超过距离,您可以停止寻找邻居。这可以在你的强力算法给出的O(n(logn + k))
而不是O(n^2)
中起作用。