【问题标题】:Calculate the distance between two integer Lists计算两个整数列表之间的距离
【发布时间】:2011-12-18 20:33:51
【问题描述】:

我正在使用 C#,并且我有两个 list<AACoordinate>,其中这些列表中的每个元素代表 x、y 和 z 空间中的一个 3D 点。

 class AACoordinate
    {
        public  int ResiNumber { get; set; }
        public double x { get; set; }
        public double y { get; set; }
        public double z { get; set; }
    }

每个列表可以包含 2000 或更多点,我的目标是将 list1 的每个点与 list2 的所有点进行比较,如果距离小于特定数字,我会记录下来.目前我正在使用 foreach 将 list1 的每个元素与 list2 的所有元素进行比较。由于点的数量,这非常慢。你有什么建议可以加快速度吗?

我的循环是:

 foreach (var resiSet in Program.atomList1)
        {
            foreach (var res in Program.atomList2)
            {
                var dis = EuclideanDistance(resiSet, res);
                if (dis < 5)
                    temp1.Add(resiSet.ResiNumber); 
            }
        }

提前感谢您的帮助。

【问题讨论】:

  • 你能分享foreach循环体吗?
  • @sll:这很慢,因为将每个点与其他点进行比较是一个n^2 操作。这就像进行选择排序。
  • 您正在描述一个 n*n 解决方案。您能否更清楚地了解“保留它”的标准?
  • 您的问题类似于最近的点对问题en.wikipedia.org/wiki/Closest_pair_of_points_problem。 SO上有几个关于它的讨论。
  • 顺便说一句,所提出的算法假设一个“单一空间”。他可能需要合并两个列表并对整个点集进行操作(每个点都有一个源列表指示符),抛出相同列表距离的结果。

标签: c# algorithm list coordinates


【解决方案1】:

您可以使用可以找到Parallel.ForEach 的并行库。 Paralel Example

【讨论】:

  • 并行处理最多为您提供线性加速。他的算法是二次的。
  • 不确定并行是否会有所帮助:由于复杂度为 m*n,因此 m 或 n 的小幅增加将使努力失败...
  • 比hee需要一个自定义解决方案,但肯定必须存在并行性,也许使用线程池。
  • @Cody 他可能更需要以某种方式降低复杂性
  • @FelicePollano 是的 :) 确实如此。在意大利,我们不喜欢二次算法,哈哈 :)
【解决方案2】:

如果你真的想比较 list1 的每个元素和 list2 的每个元素,你不会摆脱嵌套的 for。但您可以使用Parallel.ForEach 加快速度。

【讨论】:

    【解决方案3】:

    您当前的方法检查 L x R 中的每个有序对,这是一个简单的 O(n^2) 算法。想到了几个想法。

    首先,您可以尝试将两个数组中的每一个拆分为边长等于您的最大距离的立方体;那么你只需要计算 L 和 R 中元素之间的距离,如果它们不超过 1 个立方体。在最坏的情况下,这仍然是 O(n^2),但如果您的点平均相距比您的最大距离远得多,您可以在此处节省大量虚假比较。

    其次,您可以对执行距离函数的方式进行微优化。例如,您永远不需要使用 sqrt();将平方距离与最大距离平方进行比较就足够了。此外,如果您首先检查是否为 |dx|、|dy|,则可以避免使用整数乘法来获得平方距离。或 |dz|满足某些属性(即,已经大于最大距离)。

    正如其他海报所提到的,并行化始终是一个不错的选择。特别是,复杂的并行化 + 装箱策略(在第一个建议中概述)应该是一个特别可扩展、高效的解决方案。

    【讨论】:

    • 您的第一个想法与四叉树的概念非常相似 :) 但四叉树以递归方式拆分。
    【解决方案4】:

    也许实现起来有点复杂,但除此之外我没有其他想法:

    为了降低计算复杂度,您可能必须使用一些数据结构,例如 KD-Tree 或 QuadTree。

    您可以使用 KD-Tree 进行最近邻搜索,这正是您所需要的。

    1) 你为 O(n log n) 中的第一个列表构建你的 kd-tree。这必须在一个线程中完成。

    2) 对于第二个列表中的每个项目,您在 kd-tree 中查找最近的邻居(到您要查找的点的最近点),时间为 O(m log n)。如果从当前点到最近找到的点的距离小于您的增量,那么您就有了。如果您愿意,可以使用多个线程来执行此步骤。

    所以最终算法的复杂度将是 O(max(n, m) * log n) 其中 n 是第一个列表中的项目数,m 是第二个列表中的项目数。

    对于 KD 树,请参阅:

    请参阅http://home.wlu.edu/~levys/software/kd/,这似乎是一个很好的实现,在 java 和 C# 中。

    http://www.codeproject.com/KB/architecture/KDTree.aspx

    对于四叉树,请参阅:

    http://csharpquadtree.codeplex.com/

    http://www.codeproject.com/KB/recipes/QuadTree.aspx

    当然,看看维基百科什么是四叉树和kd-tree

    考虑 (2000 * log base 2(2000)) 大约是 21931.5

    而不是 2000*2000 就是 4000000,差别很大!

    使用并行算法,如果你有 4 个处理器,正常的 O(n*n) 算法每个处理器需要 1000000,我猜,如果你需要快速或几乎实时的东西,这仍然太多了。

    【讨论】:

      猜你喜欢
      • 2021-05-15
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 2014-02-19
      • 2021-01-14
      • 2010-10-30
      相关资源
      最近更新 更多