【问题标题】:Ordering an Ordered list Function in Haskell在 Haskell 中对有序列表函数进行排序
【发布时间】:2018-08-16 03:57:17
【问题描述】:

对于我的课程,我必须获取两个数字列表,对它们进行排序,然后将它们组合并按顺序输出新列表,如果列表在键入时已经按顺序排列,但如果说 9 在第一个列表的开始,所以我遇到的麻烦是在组合后对列表进行排序,在其他语言中,我会使用 for 循环来执行此操作,但在 Haskell 中不确定 这是我的代码:

merge :: Ord a => [a] -> [a] -> [a]
merge x [] = x
merge [] x = x
merge (x:xs) (y:ys) = if x < y
                          then x:(merge xs (y:ys))
                          else y:(merge (x:xs) ys)

【问题讨论】:

    标签: list sorting haskell


    【解决方案1】:

    听起来您实际上应该实现的是merge sort

    在合并排序中,您合并两个排序列表以获得一个排序列表,是的。缺少的观察是大小为 0 或 1 的列表必然已经排序。

    这意味着如果您开始将函数应用于大小为 0 或 1 的列表,然后合并该合并的结果,然后合并该结果,最终您将得到一个完全排序的列表。

    这是一个例子:

    -- Your function
    merge :: Ord a => [a] -> [a] -> [a]
    merge x [] = x
    merge [] x = x
    merge (x:xs) (y:ys) = if x < y
                              then x:(merge xs (y:ys))
                              else y:(merge (x:xs) ys)
    
    
    -- Arbitrarily split a list into two ~equally sized smaller lists.
    -- e.g. [2,7,1,8,2] -> ([2,7,1], [8,2])
    split list = splitAt ((length list) `div` 2) list
    
    -- Split a list into halves until each piece is size 0 or 1,
    -- then 'merge' them back together.
    mergeSort [] = []
    mergeSort [x] = [x]
    mergeSort list =
        let (firstHalf, secondHalf) = split list
        in merge (mergeSort firstHalf) (mergeSort secondHalf)
    

    mergeSort [2,7,1,8,2] 将评估为[1,2,2,7,8]。仅使用您的 merge 函数,列表已排序。

    【讨论】:

      【解决方案2】:

      因此,如果两个输入列表都已排序,您当前的解决方案将返回一个排序列表。如果输入列表未排序,您有 2 个选项,分别对输入列表进行排序,然后按原样合并它们,或者合并未排序的列表,然后对新列表进行排序。

      合并未排序的列表然后将它们排序为一个似乎更合理,所以这里是解决方案。我使用了快速排序的快速实现,但你可以使用任何你想要的排序算法。

      --takes 2 sorted or unsorted lists, merges them, then sorts them
      merge :: (Ord a) => [a] -> [a] -> [a]
      merge [] [] = []
      merge x [] = sort x
      merge [] y = sort y
      merge x y = sort (x ++ y)
      
      -- where first element of list is pivot
      sort :: (Ord a) => [a] -> [a]
      sort [] = []
      sort (x:xs) = sort [x'|x'<-xs, x'<=x] ++ [x] ++ sort [x'|x'<-xs, x'>x]
      

      有很多方法可以做到这一点,这种方法的缺点是即使列表已经排序,也必须重新使用列表。您可以通过检查列表是否已排序,然后在需要时对其进行排序来解决此问题。我希望这个答案会有所帮助。

      【讨论】:

      • 在这种情况下,merge xs ys = sort (xs++ys)
      • 或者确实是merge = (sort .) . (++)
      【解决方案3】:

      对于像归并排序这样的问题,您希望分而治之,以便您的输入列表始终是有序的。一种方法是将输入分解为单例,这些单例始终按定义排序,然后使您的合并函数尾部递归地插入两个列表头中较小的一个。当一个输入列表最终为空时,它会附加另一个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-28
        • 2016-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多