ВПЕРЁД ⇒
⇐ НАЗАД
Сложность программ с циклами
Невложенный цикл for
for i = 0..n-1
do_something(i)
Для случая использования невложенных for-циклов количество выполняемых итераций равно . Если сложность вычислений для одной итерации постоянна и равна , то сложность вычислений всего алгоритма равна . Таким образом, получаем, что , то есть время работы алгоритма линейно зависит от .
Вложенные циклы for
Простой случай вложенных циклов
for i = 0..n-1
for j = 0..n-1
do_something(i, j)
В представленном случае каждый из циклов содержит итераций, тогда всего итераций с вызовом do_something(i, j) в алгоритме будет , откуда следует .
По мере увеличения числа вложенных циклов будет происходить пропорциональное увеличение степени полинома, характеризующего сложность вычислений.
for i = 0..n-1
for j = 0..n-1
for k = 0..n-1
do_something(i, j, k) // O(n^3)
for i = 0..n-1
for j = 0..n-1
for k = 0..n-1
for l = 0..n-1
do_something(i, j, k, l) // O(n^4)
Сложный случай вложенных циклов
Предположим, что имеется следующая ситуация:
for i = 0..n-1
for j = 0..i
do_something(i, j)
В данном случае количество итераций вложенного цикла уже зависит от . Как же быть в этом случае? Задача получения оценки сложности алгоритма в этом случае может быть решена несколькими способами.
Грубая оценка временной сложности
Число итераций вложенного цикла for j = 0..i для каждой из итераций внешнего цикла for i = 0..n-1 не превышает . То есть временная сложность работы алгоритма не будет превышать временную сложность ранее рассмотренного алгоритма:
for i = 0..n-1
for j = 0..n-1
do_something(i, j)
Из этого следует: .
Точная оценка временной сложности
Сложность вычислений рассматриваемого алгоритма можно выразить в виде следующей формулы:
, где - временная сложность -й итерации внешнего цикла.
Элементы отображают число итераций внутреннего цикла и изменяются следующим образом:
, , …,
Из характера изменения элементов видно, что они представляют собой члены арифметической прогрессии, так как каждый последующий элемент отличается от предыдущего на одну и ту же величину: . Тогда - это сумма членов указанной арифметической прогрессии.
Сумма членов арифметической прогрессии считается по следующей формуле:
Таким образом, для нашего исследуемого алгоритма получаем:
Графический способ получения оценки сложности вычислений
На рисунке-гистограмме показаны элементы упомянутой арифметической прогрессии, которая отражает процесс изменения количества итераций внутреннего цикла программы с ростом порядкового номера итерации внешнего цикла.
for i = 0..n-1
for j = 0..i
do_something(i, j)

Необходимо оценить сумму указанных элементов. Сумма элементов - площадь фигуры, образованной синими столбцами (площадь синего треугольника). Очевидно, что площадь синего треугольника - половина площади красного квадрата (в котором расположен треугольник). Площадь красного квадрата равна , тогда площадь синего треугольника равна . Таким образом, получаем:
.
Цикл while, вложенный в цикл for
for i = 0..n-1
j = 0
while j*j <= i // граница i будет достигнута при j равном
// квадратному корню из i
do_something(i, j)
j = j + 1
Упрощаем процесс анализа путём замены условия в цикле while:
for i = 0..n-1
j = 0
while j*j <= n // граница n будет достигнута при j равном
// квадратному корню из n
do_something(i, j)
j = j + 1
ВПЕРЁД ⇒
⇐ НАЗАД
Источники
Категория
Теги