在Haskell中排序有序列表函数

时间:2018-03-07 22:27:18

标签: list sorting haskell

对于我的课程,我必须取两个数字列表,对它们进行排序,然后将它们组合起来并按顺序输出新列表,如果列表在键入时已按顺序排序,但如果说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)

3 个答案:

答案 0 :(得分:3)

听起来你实际应该实现的是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功能,列表已经过排序。

答案 1 :(得分:0)

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

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

--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]

有很多方法可以做到这一点,即使列表已经排序,这种方式也有不得不求助于列表的缺点。您可以通过检查列表是否已排序,然后根据需要对它们进行排序来解决此问题。我希望这个答案有所帮助。

答案 2 :(得分:0)

对于像合并排序这样的问题,您需要分而治之,以便始终对您的输入列表进行排序。一种方法是通过将输入分解为单体(通常按定义排序),然后使合并函数以递归方式插入两个列表头中较小的一个来实现此目的。当一个输入列表最终为空时,它会附加另一个。