我正在使用2个辅助函数进行“合并排序”。第一个辅助函数将列表拆分为一个列表,将奇数和偶数索引放在单独的列表中。
Example: [1,2,3,4,5,6]
Returns: ([1,3,5],[2,4,6])
第二个辅助函数假定列表已排序并合并它们。
我将使用这两个函数实现一个未排序列表的合并排序。
我有这个非常低效的部分,基本上分裂(长度 - 1)* 2次并合并列表(长度 - 1)次。
sort length (z:zs)
| length == 0 = (z:zs)
| otherwise = sort (length - 1) (merge (fst (split(z:zs))) (snd (split(z:zs)))
我正在调用split两次以获得与第一次拆分相同的信息,并且我没有足够的递归(每个列表只是一个单例,然后将它们全部合并)。
如何递归单例并同时拉出元组的两个元素?
提前感谢您提供任何帮助。
答案 0 :(得分:2)
您可以使用uncurry
将merge
转换为非咖喱函数,并将split(z:zs)
作为参数传递:
sort (length - 1) $ uncurry merge $ split (z:zs)
uncurry
函数将a -> b -> c
类型的函数转换为(a, b) -> c
类型的函数。在您的情况下,merge
的类型为[a] -> [a] -> [a]
,而uncurry merge
的类型为([a], [a]) -> [a]
,而([a], [a])
的返回类型为split
。
或者,您只需使用let
或where
子句来引用split
的结果:
let (left, right) = split (z:zs)
in sort (length - 1) $ merge left right
是改进版的:
let res = split (z:zs)
in sort (length - 1) $ merge (fst res) (snd res)
作为旁注,您的sort
功能不正确。你的定义是:
sort length (z:zs) = ...
但是这只匹配非空列表。如果案件length == 0
永远不会发生,那么这也是毫无用处的。
您对sort
的定义是考虑空案例的原因:
sort _ [] = []
sort length (z:zs) = ...