Recursion 理解两个尾部递归映射函数的性能差异

Recursion 理解两个尾部递归映射函数的性能差异,recursion,ocaml,tail-recursion,map-function,Recursion,Ocaml,Tail Recursion,Map Function,从Jason Hickey对Objective Caml的介绍中,我们有一个尾部递归映射函数: let rec rev_accum result = function h::tl -> rev_accum (h :: result) tl | [] -> result let rec rec_map f result = function h :: tl -> rec_map f (f h :: result) tl | [] -&

从Jason Hickey对Objective Caml的介绍中,我们有一个尾部递归映射函数:

let rec rev_accum result = function  
    h::tl -> rev_accum (h :: result) tl
    | [] -> result

let rec rec_map f result = function
    h :: tl -> rec_map  f (f h :: result)   tl 
    | [] -> result 

let map1 f l = rev_accum  [] ( rec_map f [] l )
它将遍历列表两次。考虑这个替代方案:

let rec rec_map2 f result = function
    h :: tl -> rec_map2  f ( result @[f h]) tl 
    | [] -> result 

let map2 f l = rec_map2 f [] l ; 

第二个会比第一个快吗?

重复添加到列表末尾需要的时间是列表最终长度的二次方。另一种说法是它遍历列表n次,很容易超过两次。因此,第二个实现通常要慢得多。第一个实现是线性的,即使它遍历列表两次


(当然,您不知道函数
f
的性能)

据我所知,在列表中添加一项。在C中,当它由链接列表实现时,它是O(1),为什么ocaml需要遍历整个列表?如果您的C代码保持指向列表最后一个元素的指针,那么添加元素不需要遍历列表。但是对于单链接列表,只有指向head元素的指针,因此附加到列表需要遍历。