使用head :: tail进行F#排序

时间:2011-05-23 16:11:01

标签: f# tail-recursion

我正在尝试编写一个使用head :: tail的递归函数。我理解列表中第一个元素和尾部的头部是列表中的所有其他元素。我也理解递归是如何工作的。我想知道的是如何对列表中的元素进行排序。有没有办法比较头部与尾部的每个元素然后选择最小的元素?我在C ++中的背景,我不允许使用List.sort()。知道如何去做吗?我查看了msdn网站上的教程,但仍然没有运气

2 个答案:

答案 0 :(得分:2)

在担心使用的数据结构之前,您需要确定排序方法。如果您要执行插入排序,您可能希望从列表末尾开始并在每个递归级别插入一个项目,小心如何处理插入本身。

从技术上讲,在任何特定级别,您只能访问一个数据元素,但是您可以将特定数据元素作为参数传递以保留它。例如,这里是插入排序算法的插入部分,它假定列表已排序。

let rec insert i l =
    match l with
    | [] -> [i]
    | h::t -> if h > i then
                  i::l
              else
                  h::(insert i t)

请注意我现在如何访问两个元素,缓存的元素和其余元素。另一种变体是合并排序,其中有两个排序列表,因此有两个项可用于任何特定迭代。

Daniel的评论回答提到了一个特定的实现(quicksort),如果你感兴趣的话。

最后,由于结构刚性和所需的分配数量,列表不是最佳的排序算法。鉴于所有已知的排序算法都是> O(n)复杂度,您可以将列表转换为数组,以便在不损害渐近性能的情况下提高性能。

编辑:
请注意,上面不是尾递归格式,您需要执行以下操作:

let insert i l =
    let rec insert i l acc =
        match l with
        | [] -> List.foldBack (fun e a -> e :: a) acc [i]
        | h::t -> if h > i then
                      List.foldBack (fun e a -> e :: a) acc i::l
                  else
                      insert i l (i::acc)
    insert i l []

我不记得反转列表的最佳方法,所以选择https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/lists

的示例

答案 1 :(得分:1)

这是F#

中快速排序算法的基于列表的递归实现
let rec quicksort list =
    match list with
    | [] -> []
    | h::t ->
        let lesser = List.filter ((>) h) t
        let greater = List.filter ((<=) h) t
        (quicksort lesser) @[h] @(quicksort greater)