From 899afc7287cab21833580ca4a8467f9b718e2b4d Mon Sep 17 00:00:00 2001 From: hasufell Date: Tue, 2 Dec 2014 18:56:40 +0100 Subject: [PATCH] ALGO: fix runtime complexity in KDTree The old code in fact increased the complexity to O(n^2), because we applied 'elem' which is O(n) to every element of xs. Instead we compare (in case of partitioning against Y) the y-value of every element of xs with the y-value of the pivot which tells us if x lies within ys. --- Algorithms/KDTree/KDTree.hs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Algorithms/KDTree/KDTree.hs b/Algorithms/KDTree/KDTree.hs index 5822fd2..3494715 100644 --- a/Algorithms/KDTree/KDTree.hs +++ b/Algorithms/KDTree/KDTree.hs @@ -69,15 +69,16 @@ kdTree xs' = go (sortedX xs') (sortedY xs') -- partition' (pivot xs) (ys, xs) -- and get ((y1, y2), (x1, x2)). partition' :: PT -- ^ the pivot to partition against + -> (PT -> PT -> Ordering) -- ^ ptCmpY or ptCmpX -> ([PT], [PT]) -- ^ both lists (X, Y) or (Y, X) -> (([PT], [PT]), ([PT], [PT])) -- ^ ((x1, x2), (y1, y2)) or -- ((y1, y2), (x1, x2)) -partition' piv (xs, ys) = ((x1, x2), (y1, y2)) +partition' piv cmp' (xs, ys) = ((x1, x2), (y1, y2)) where y1 = takeWhile (/= piv) ys y2 = tailDef [] . dropWhile (/= piv) $ ys - x1 = foldr (\x y -> [x | x `elem` y1] ++ y) [] xs - x2 = foldr (\x y -> [x | x `elem` y2] ++ y) [] xs + x1 = foldr (\x y -> [x | cmp' x piv == LT] ++ y) [] xs + x2 = foldr (\x y -> [x | cmp' x piv == GT] ++ y) [] xs -- |Partition two sorted lists of points X and Y against the pivot of @@ -85,7 +86,7 @@ partition' piv (xs, ys) = ((x1, x2), (y1, y2)) -- pivot. partitionY :: ([PT], [PT]) -- ^ both lists (X, Y) -> (([PT], [PT]), ([PT], [PT])) -- ^ ((x1, x2), (y1, y2)) -partitionY (xs, ys) = partition' (fromJust . pivot $ ys) (xs, ys) +partitionY (xs, ys) = partition' (fromJust . pivot $ ys) ptCmpY (xs, ys) -- |Partition two sorted lists of points X and Y against the pivot of @@ -94,7 +95,7 @@ partitionY (xs, ys) = partition' (fromJust . pivot $ ys) (xs, ys) partitionX :: ([PT], [PT]) -- ^ both lists (X, Y) -> (([PT], [PT]), ([PT], [PT])) -- ^ ((x1, x2), (y1, y2)) partitionX (xs, ys) = (\(x, y) -> (y, x)) - . partition' (fromJust . pivot $ xs) $ (ys, xs) + . partition' (fromJust . pivot $ xs) ptCmpX $ (ys, xs) -- |Execute a range search in O(log n). It returns a tuple