为什么List.length的复杂性是线性的?

时间:2014-07-02 16:39:34

标签: list f#

据我所知,列表是单链接实现的,因此它们实际上没有一个可以固定长度的常量结构,但是每个节点应该知道最后一个元素到底有多少个节点?没有办法将节点添加到某个现有列表,并且该节点无法确定它在恒定时间内表示的列表长度,前提是现有节点已有该信息。

我可以理解为什么在Haskell中这不起作用,例如,由于懒惰,但据我所知,F#列表并不是懒惰的。那么问题就在于额外的内存开销吗?

2 个答案:

答案 0 :(得分:4)

对我而言,就像典型的记忆与时间表现一样。

如果标准f#list具有你建议的实现,那么它将需要更多的内存(考虑一百万长的bool列表)。使用此类列表的每个人都必须处理它。除了编写完全新的列表实现之外,没有简单的方法可以选择退出。

另一方面,创建一个新类型可以相当简单,它可以存储基于F#List的每个元素的后续列表的长度。如果需要,您可以自己实现它。那些不需要它的人将使用标准实施。

答案 1 :(得分:4)

我并不经常发现自己需要知道列表的长度,就像你需要退出for循环一样,就像使用命令式语言中的数组一样。

对于那些您确实需要尽快知道长度的极少数情况,您可以通过评论中的CarstenKönig建议,并将'a list变为('a * int) list,其中每个节点保持长度尾巴作为元组元素。

然后你可以这样:

let push lst e =
    match lst with
    | (_, c)::_ -> (e, c + 1) :: lst
    | [] -> [e, 0]
要匹配的

lengthpop个函数。

对于所有其他情况,我称之为过早优化。