我需要在 SML 中为家庭作业实施快速排序,但我迷路了。我以前不熟悉快速排序是如何实现的,所以我阅读了它,但我读到的每个实现都是命令式的。这些看起来不太难,但我不知道如何在功能上实现快速排序。
维基百科恰好有标准 ML 中的快速排序代码(这是我的作业所需的语言),但我不明白它是如何工作的。
维基百科代码:
val filt = List.filter
fun quicksort << xs = let
fun qs [] = []
| qs [x] = [x]
| qs (p::xs) = let
val lessThanP = (fn x => << (x, p))
in
qs (filt lessThanP xs) @ p :: (qs (filt (not o lessThanP) xs))
end
in
qs xs
end
特别是,我不明白这一行:qs (filt lessThanP xs) @ p :: (qs (filt (not o lessThanP) xs))
. filt 将返回 xs 中小于 p* 的所有内容的列表,该列表与 p 连接,后者被 cons-ed 到所有 >= p.*
*假设当 x < p 时 << (x, p) 函数返回 true。当然不必如此。
实际上,把这个写出来有助于我理解发生了什么。无论如何,我正在尝试将该 SML 函数与 wiki 的快速排序伪代码进行比较,如下所示。
函数快速排序(数组,“左”,“右”)
// If the list has 2 or more items
if 'left' < 'right'
// See "Choice of pivot" section below for possible choices
choose any 'pivotIndex' such that 'left' ≤ 'pivotIndex' ≤ 'right'
// Get lists of bigger and smaller items and final position of pivot
'pivotNewIndex' := partition(array, 'left', 'right', 'pivotIndex')
// Recursively sort elements smaller than the pivot
quicksort(array, 'left', 'pivotNewIndex' - 1)
// Recursively sort elements at least as big as the pivot
quicksort(array, 'pivotNewIndex' + 1, 'right')
其中分区定义为
// left is the index of the leftmost element of the array
// right is the index of the rightmost element of the array (inclusive)
// number of elements in subarray = right-left+1
function partition(array, 'left', 'right', 'pivotIndex')
'pivotValue' := array['pivotIndex']
swap array['pivotIndex'] and array['right'] // Move pivot to end
'storeIndex' := 'left'
for 'i' from 'left' to 'right' - 1 // left ≤ i < right
if array['i'] < 'pivotValue'
swap array['i'] and array['storeIndex']
'storeIndex' := 'storeIndex' + 1
swap array['storeIndex'] and array['right'] // Move pivot to its final place
return 'storeIndex'
那么,分区到底发生在哪里?还是我错误地考虑了 SML 快速排序?