如何提高函数的复杂性,为其上的每个点对列表进行排序?

时间:2015-03-02 08:08:03

标签: algorithm sorting haskell data-structures

以下功能:

sortByDist :: (Ord a, Floating a, RealFrac a) => [V2 a] -> Map (V2 a) [V2 a]
sortByDist graph = Map.fromList $ map sort graph where
    sort point = (point, sortBy (comparing (distance point)) graph)

将列表上的每个点P映射到按其到P的距离排序的点列表。例如,sortByDist [a, b, c, d] Map.! b是列表[b,a,c,d],如果a是距离b最近的点,c是距离第二近的点,d是第3点。

由于它为每个元素执行n * log n排序,因此复杂度为n^2 * log n。这与对N个点列表进行排序所需时间的基准一致:

points  time
200     0m0.086s
400     0m0.389s
600     0m0.980s
800     0m1.838s
1000    0m2.994s
1200    0m4.350s
1400    0m6.477s
1600    0m8.726s
3200    0m39.216s    

理论上可以改善多少?是否可以将其降为N * log N

1 个答案:

答案 0 :(得分:3)

作为luqui commented,使用四叉树或类似物可能会有所帮助。构建树应该采用O(n log n):log n遍,每个都是O(n)选择和分区。获得树后,可以遍历它以构建列表。节点及其子节点的列表之间的差异通常应该很小,而当某些节点很大时,应该倾向于强迫其他节点小。因此,使用自适应排序(例如,自适应合并排序或自适应展开排序)应该提供良好的性能,但分析复杂性并不容易。如果您想尝试进行一些共享,则必须使用序列类型(例如Data.Sequence)表示列表,然后尝试找出各种比例的正方形之间的关系。我对这种降低时间复杂性的方法的可能性表示严重怀疑。