私はアルゴリズム分析と SML に不慣れで、次の SML 関数の平均的なケースの実行時間に夢中になりました。私の考えに対するフィードバックをいただければ幸いです。
fun app([]) = []
| app(h::t) = [h] @ app(t)
したがって、すべての再帰の後、一連の単一要素リスト (および 1 つの要素なしリスト) になります。
[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) 対 Θ(n²)!) しかし、これL @ R
は線形ではなく一定の時間がかかると仮定していませんか? たとえば、追加の場合は true になります。
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
ますか、それとも私の分析は(少なくともある程度)正しいですか?