Sorting 哈斯克尔。如何在mergesort中打印每个已排序元素的数组

Sorting 哈斯克尔。如何在mergesort中打印每个已排序元素的数组,sorting,haskell,recursion,functional-programming,mergesort,Sorting,Haskell,Recursion,Functional Programming,Mergesort,我正在使用Haskell测试我的mergesort函数,但我不知道将trace函数放在哪里,这样每当数组中的元素被排序时它都会显示出来 例如,如果我输入[4,3,2,1]进行排序,它应该为每次迭代打印数组,直到得到排序: [4,3,2,1] [3,4,2,1] [3,4,1,2] [1,2,3,4] 代码: merge::Ord a=>[a]->[a]->[a]->[a] 合并[]ys=ys 合并xs[]=xs 合并(x:xs)(y:ys)| x([a],[a]) 将X减半=(取左X X,放下

我正在使用Haskell测试我的mergesort函数,但我不知道将trace函数放在哪里,这样每当数组中的元素被排序时它都会显示出来

例如,如果我输入[4,3,2,1]进行排序,它应该为每次迭代打印数组,直到得到排序:

[4,3,2,1]
[3,4,2,1]
[3,4,1,2]
[1,2,3,4]
代码:

merge::Ord a=>[a]->[a]->[a]->[a]
合并[]ys=ys
合并xs[]=xs
合并(x:xs)(y:ys)| x([a],[a])
将X减半=(取左X X,放下左X X)
其中lhx=长度xs`div`2
msort::Ord a=>[a]->[a]
msort[]=[]
msort[x]=[x]
msort xs=合并(msort left)(msort right)
其中(左、右)=将X减半

您无法在每个步骤中轻松跟踪整个部分排序的列表,因为您没有在任何地方构建或记录该信息。该代码只是直接构建最终的输出列表,对该列表求值时会根据需要递归调用
msort
,以查找下一个元素

但是,您可以在合并期间记录每个比较,这些信息足以验证步骤。例如,添加以下跟踪:

merge :: (Ord a, Show a) => [a] -> [a] -> [a]
merge [] ys         = ys
merge xs []         = xs
merge (x:xs) (y:ys)
  | x < y     = trace sorted  $ x:merge xs (y:ys)
  | otherwise = trace swapped $ y:merge (x:xs) ys
  where
    sorted = concat
      ["sorted:  ", show x, " < ", show y]
    swapped = concat
      ["swapped: ", show x, " >= ", show y]
因为我们只是获取结果的第一个元素,所以这只需要执行尽可能多的比较来找到最小值。(编写巧妙的惰性合并排序在避免工作方面可以做得更好一些。)

注意元素的求值顺序如何显示算法的树结构:

  #0
   │ #1
   └┬─┘    #3
    │       │ #4
    │   #2  └┬─┘
    │    └┬──┘   #5
    └┬────┘       │ #6
     │            └┬─┘    #8
     │             │       │ #9
     │             │   #7  └┬─┘
     │             │    └┬──┘
     │             └┬────┘
     └┬─────────────┘
因此,最终结果是两个排序的一半,
[1,2,3,9,10]
[4,5,6,7,8]
,但程序不必进行任何剩余的合并,因为我们已经确定
1
是最小元素,因为子列表都已排序,并且
1<4

所以我要说你的功能看起来不错!但你不必相信我的话;您还可以使用属性测试包(如QuickCheck)在随机样本输入上测试它,例如,通过验证它是否生成排序结果,或根据已知的正确
排序
实现进行检查:

> :set -package QuickCheck
> import Test.QuickCheck

> isSorted xs = and $ zipWith (<=) xs (drop 1 xs)
> quickCheck $ \ xs -> isSorted (msort (xs :: [Int]))
…
+++ OK, passed 100 tests.

> quickCheck $ \ xs -> sort (xs :: [Int]) == msort xs
…
+++ OK, passed 100 tests.
>:设置-包快速检查
>导入测试。快速检查
>isSorted xs=和$zipWith(快速检查$\xs->isSorted(msort(xs::[Int]))
…
+++好的,通过了100次测试。
>快速检查$\xs->sort(xs::[Int])==msort-xs
…
+++好的,通过了100次测试。

每个步骤中都没有“整个数组”,而且由于计算太慢,也没有精确的“元素排序时间”。感谢您的清晰解释和代码!终于让它工作了。
  #0
   │ #1
   └┬─┘    #3
    │       │ #4
    │   #2  └┬─┘
    │    └┬──┘   #5
    └┬────┘       │ #6
     │            └┬─┘    #8
     │             │       │ #9
     │             │   #7  └┬─┘
     │             │    └┬──┘
     │             └┬────┘
     └┬─────────────┘
> :set -package QuickCheck
> import Test.QuickCheck

> isSorted xs = and $ zipWith (<=) xs (drop 1 xs)
> quickCheck $ \ xs -> isSorted (msort (xs :: [Int]))
…
+++ OK, passed 100 tests.

> quickCheck $ \ xs -> sort (xs :: [Int]) == msort xs
…
+++ OK, passed 100 tests.