Sorting 哈斯克尔。如何在mergesort中打印每个已排序元素的数组
我正在使用Haskell测试我的mergesort函数,但我不知道将trace函数放在哪里,这样每当数组中的元素被排序时它都会显示出来 例如,如果我输入[4,3,2,1]进行排序,它应该为每次迭代打印数组,直到得到排序: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,放下
[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.