【问题标题】:Slow insertion sorting慢速插入排序
【发布时间】:2013-08-18 13:35:55
【问题描述】:
insertionSort :: (Ord a) => [a] -> [a]
insertionSort (x:xs) = insertionSortIter [x] xs 
    where insertionSortIter sorted []      =  sorted  
          insertionSortIter sorted (x:xs)  =  insertionSortIter (insert x sorted (length sorted)) xs
          insert x list n   --insert x in list at n
                | n == 0    = x:list
                | x < list !! (n - 1)   = insert x list (n - 1)
                | otherwise = firstns ++ (x:other) where (firstns, other) = splitAt n list
-- [1..10000] 30s                    
mergeSort :: (Ord a) => [a] -> [a]
mergeSort (x:[])      = [x]
mergeSort  list       = merge (mergeSort list1) (mergeSort list2)
        where (list1, list2) = splitAt (length list `div` 2) list
              merge [] list       = list
              merge list []       = list
              merge (x:xs) (y:ys) = if x < y then x:(merge xs (y:ys)) else y:(merge (x:xs) ys)
-- [1..10000] 2.4s

执行时间由构建时间指定(1 或 1.5 秒)。但您仍然可以感受到不同。

问题可能是insert 函数或firstns ++ (x:other) 的每个分支的执行速度太慢。但无论如何,要将项目放在列表的末尾,我需要遍历整个列表 O(n)。

【问题讨论】:

  • 还有什么问题?
  • insertionSortIter 迭代 O(n) 个位置并在每次迭代时调用 O(n) 时间 !! 运算符,使其 O(n^2) 仅插入单个项目.不要那样做。
  • ДМИТРИЙ,很高兴在那里见到你。为何这么慢。我做错了什么。
  • @DanielWagner,好的。 !!++ 在这种情况下很糟糕。我该怎么办?
  • @IVlad,在这个综合测试中 ([1..n]) 应该比归并排序更快。

标签: haskell mergesort insertion-sort


【解决方案1】:

您的insert 功能很慢。以下是如何进行插入排序:

insertionSort :: Ord a => [a] -> [a]
insertionSort xs = f [] xs
  where
    f rs []     = rs
    f rs (x:xs) = f (insert x rs) xs

    insert x []         = [x]
    insert x rrs@(r:rs) = if x < r then x:rrs else r:insert x rs

如果混淆,rrs@(r:rs) 语法意味着rrs 是整个列表,r 是它的头部,rs 是它的尾部。

insert 遍历列表并取出所有应该在x 前面的元素,然后它输出x,然后是应该在x 之后的元素。

【讨论】:

  • 很好,谢谢!在最好的情况下,在原始插入排序 O(n) 中。所以在最坏的情况下有 O(n),我们似乎无能为力。
  • 你可以用 foldr 代替 f。
  • 所以最终的代码是insertionSort (x:xs) = foldr insert [x] xs。非常好。出于某种原因,我认为我们无法在 foldr 中获取列表。很高兴这种刻板印象被打破了。嗯,但使用 foldr 排序的非线性工作速度较慢。
猜你喜欢
  • 1970-01-01
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
相关资源
最近更新 更多