Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Haskell中有序列表函数的排序_List_Sorting_Haskell - Fatal编程技术网

List Haskell中有序列表函数的排序

List Haskell中有序列表函数的排序,list,sorting,haskell,List,Sorting,Haskell,在我的课程作业中,我必须获取两个数字列表,对它们进行排序,然后将它们合并,并按顺序输出新列表。如果列表在键入时已按顺序排列,则此操作有效,但如果第一个列表的开头是9,则此操作无效。因此,我遇到的麻烦是在合并后对列表进行排序,在其他语言中,我会使用for循环,但在Haskell中不确定 下面是我的代码: merge :: Ord a => [a] -> [a] -> [a] merge x [] = x merge [] x = x merge (x:xs) (y:ys) = i

在我的课程作业中,我必须获取两个数字列表,对它们进行排序,然后将它们合并,并按顺序输出新列表。如果列表在键入时已按顺序排列,则此操作有效,但如果第一个列表的开头是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)
merge::Ord a=>[a]->[a]->[a]->[a]
合并x[]=x
合并[]x=x
合并(x:xs)(y:ys)=如果x
因此,如果两个输入列表都已排序,则当前解决方案将返回一个已排序列表。如果输入列表未排序,则有两个选项,分别对输入列表进行排序,然后按原样合并,或者合并未排序的列表,然后对新列表进行排序

合并未排序的列表,然后将其作为一个列表进行排序似乎更合理,因此下面是解决方案。我已经使用了快速排序的快速实现,但是您可以使用任何您想要的排序算法

--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个已排序或未排序的列表,合并它们,然后对它们进行排序
合并::(Ord a)=>[a]->[a]->[a]->[a]
合并[][]=[]
合并x[]=排序x
合并[]y=排序y
合并x y=排序(x++y)
--其中列表的第一个元素是pivot
排序::(Ord a)=>[a]->[a]
排序[]=[]
排序(x:xs)=排序[x'| x'x]

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

听起来你实际上应该实现的是

在“合并排序”中,将两个已排序列表合并为一个已排序列表,是的。缺少的观察是,大小为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)
——您的函数
合并::Ord a=>[a]->[a]->[a]
合并x[]=x
合并[]x=x
合并(x:xs)(y:ys)=如果x([2,7,1],[8,2])
拆分列表=拆分((长度列表)`div`2)列表
--将列表分成两半,直到每个部分的大小为0或1,
--然后将它们“合并”在一起。
合并排序[]=[]
合并排序[x]=[x]
合并排序列表=
let(上半部分,下半部分)=拆分列表
合并中(合并排序上半部分)(合并排序下半部分)

mergeSort[2,7,1,8,2]
将计算为
[1,2,2,7,8]
。仅使用您的
merge
功能,列表已排序。

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

在本例中,
merge xs ys=sort(xs++ys)
。或者实际上是
merge=(sort.)。(++)