【发布时间】:2012-12-08 06:03:31
【问题描述】:
我是算法分析和 SML 的新手,并且对以下 SML 函数的平均情况运行时感到困惑。我希望能得到一些关于我的想法的反馈。
fun app([]) = []
| app(h::t) = [h] @ app(t)
所以在每次递归之后,我们都会得到一堆单元素列表(和一个无元素列表)。
[1]@[2]@[3]@...@[n]@[]
其中n 是原始列表中元素的数量,1, 2, 3, ..., n 只是为了说明我们正在谈论的原始列表中的哪些元素。 L @ R 所花费的时间与列表 L 的长度成线性关系。假设 A 是 @ 为每个元素所花费的恒定时间,我想这就像:
[1,2]@[3]@[4]@...@[n]@[] took 1A
[1,2,3]@[4]@...@[n]@[] took 2A
[1,2,3,4]@...@[n]@[] took 3A
...
[1,2,3,4,...,n]@[] took (n-1)A
[1,2,3,4,...,n] took nA
因此,我认为当时的重现会是这样的:
T(0) = C (if n = 0)
T(n) = T(n-1) + An + B (if n > 0)
其中C 只是基本情况app([]) 的最终匹配,B 是h::t 的常量。关闭递归,我们会得到这个(证明省略):
T(n) = (n²+n)A/2 + Bn + C = (A/2)n² + (A/2)n + Bn + C = Θ(n²)
这是我自己的结论,与提供给我的答案不同,即:
T(0) = B (if n = 0)
T(n) = T(n-1) + A (if n > 0)
封闭式
T(n) = An + B = Θ(n)
这是完全不同的。 (Θ(n) vs Θ(n²)!)但这不是假设L @ R 需要恒定时间而不是线性时间吗?例如,加法是正确的
fun add([]) = 0
| add(h::t) = h + add(t) (* n + ... + 2 + 1 + 0 *)
甚至是串联
fun con([]) = []
| con(h::t) = h::con(t) (* n :: ... :: 2 :: 1 :: [] *)
我是误解了L @ R 的存在方式还是我的分析(至少在某种程度上)正确?
【问题讨论】:
-
@与左操作数列表的大小成线性关系,但在这里它总是在单元素列表上调用。 -
我想我明白了。我正在以相反的顺序添加列表,即 [1]@[2]@[3]@[4]@...@[n]@[] 最终将是 [1]@[2,3, ...,n]。是这样吗?
-
是的,没错。因此,您执行的每个附加都是恒定的时间。