Если каждая внутренняя операция равна Θ (1), List.fold
и List.foldBack
- это O (n), где n
- длина списка.
Однако, чтобы оценить асимптотическую сложность времени, вам нужно полагаться на Θ (1) операций. В вашем примере все немного тоньше.
Предположим, вам нужно объединить n
списки, где каждый список содержит m
элементов. Поскольку @
равно O(n)
длины левого операнда, мы имеем сложность foldBack
:
m + ... + m // n occurences of m
= O(m*n)
и fold
:
0 + m + 2*m + ... + (n-1)*m // each time length of left operand increases by m
= m*n*(n-1)/2
= O(m*n^2)
Следовательно, при вашем наивном способе использования @
, foldBack
является линейным, в то время как fold
является квадратичным по отношению к размеру входных списков.
Следует отметить, что @
является ассоциативным (a @ (b @ c) = (a @ b) @ c); следовательно, результаты одинаковы для fold
и foldBack
в этом случае.
На практике, если внутренний оператор неассоциативен, нам нужно выбрать правильный порядок, используя fold
или foldBack
. И List.foldBack
в F # делается хвост-рекурсивным путем преобразования списков в массивы; эта операция также имеет некоторые накладные расходы.