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