我想使用合并排序算法。 mergeSort 是等待合并功能作为第一个参数的主要功能。有谁有想法,在我的情况下问题在哪里?非常感谢你提前。
mergeSort xs = merge xs
mergeDesc xs = reverse (mergeAsc xs)
mergeAsc [] = []
mergeAsc [x] = [x]
mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs `div` 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) | x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
答案 0 :(得分:5)
为您的函数添加类型签名,然后问题就变得很明显了:
mergeAsc, mergeDesc :: Ord a => [a] -> [a]
mergeDesc xs = reverse (mergeAsc xs)
mergeAsc [] = []
mergeAsc [x] = [x]
mergeAsc xs = merge (mergeAsc top) (mergeAsc bottom) where (top, bottom) = splitAt (length xs `div` 2) xs
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) | x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
因此,如果您将mergeSort
定义为merge
,那么当您真正希望它订购单个列表时,它只是合并两个有序列表的函数。您可以使用
mergeSort xs = mergeAsc xs
或简单而且最好,
mergeSort = margeAsc
请注意,mergeDesc
并不是很好:首先按错误的顺序对列表进行排序,然后将其反转?在Haskell中,您希望您的算法足够灵活,可以自行处理不同排序的内容。所以你要定义
mergeSortBy :: (a->a->Ordering) -> [a] -> [a]
mergeSortBy cmp = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merge (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = case x`cmp`y of
LT -> x : merge xs (y:ys)
_ -> y : merge (x:xs) ys
然后,您只需定义mergeSort = mergeSortBy compare
和mergeSortDesc = mergeSortBy (flip compare)
。
同时观察如何使merge
本地函数阻止您在实现中出现的错误。
它说应该声明为:mergeSort ::([a] - &gt; [a] - &gt; [a]) - &gt; [a] - &gt; [a]作为接受合并函数作为第一个参数的函数...
这很奇怪,它不应该被称为mergeSort
,而是sortWithMerge
或其他东西。无论如何,这样做很简单:只需抛出cmp
(仅在merge
子函数中使用!)并将其替换为参数而不是在本地定义。
sortWithMerge :: ([a]->[a]->[a]) -> [a] -> [a]
sortWithMerge merger = mSort
where
mSort [] = []
mSort [x] = [x]
mSort xs = merger (mSort top) (mSort bottom)
where (top, bottom) = splitAt (length xs `quot` 2) xs