ВПЕРЁД

НАЗАД



Порядок роста сложности вычислений

- сложность вычислений (время работы) алгоритма, представляющая собой функцию количества операций от размера входных данных .

В функции времени работы от размера входных данных нас, в первую очередь, интересует сам характер зависимости, то есть является ли эта зависимость линейной, или нелинейной (например, степенной, экспоненциальной и т.п.).

Несмотря на то, что в некоторых случаях можно определить точное время работы алгоритма, обычно не стоит тратить лишние усилия для получения оценки с высокой точностью. Для достаточно больших входных данных постоянные множители и слагаемые низшего порядка, фигурирующие в выражении для точного времени работы алгоритма, подавляются эффектами, вызванными увеличением размера входных данных.

Рассмотрим, для примера, полиномиальную зависимость . Мы хотим определить характер этой зависимости. Для этого необходимо избавиться от всех слагаемых, которые с бесконечным ростом параметра начинают вносить пренебрежительно малый вклад в эту зависимость. Тем самым мы упростим рассматриваемую зависимость. Благодаря упрощению зависимости, по оставшимся слагаемым мы сможем легко определить, как на самом деле ведёт себя эта зависимость. Наибольший вклад в характер полиномиальной зависимости вносит самый старший член полинома. Докажем это.

Поскольку мы утверждаем, что в старший член (полином) вносит наибольший вклад в поведение зависимости, то это означает, что полином с ростом параметра должен расти быстрее, чем полином , причём отношение первого полинома ко второму будет увеличиваться до бесконечности по мере бесконечного увеличения параметра . И это действительно так. Рассмотрим отношение двух указанных полиномов:

.

Очевидно, что с бесконечным ростом параметра дробь также бесконечно растёт:

  • стремится к бесконечности;
  • поскольку и стремятся к нулю, то стремится к .

Таким образом, для , стремящегося к плюс бесконечности, получаем, что .

У старшего члена исходного полинома (то есть у выражения ) конкретное значение множителя нам не важно, так как оно оценивается в некотором приближении, то есть фактическое значение множителя может отличаться от оценённого. Например, в зависимости от используемого процессором набора инструкций, одни и те же операции разными процессорами могут выполняться за различное количество инструкций/тактов, поэтому мы можем лишь только предполагать, какие на самом деле значения множителей в слагаемых имеет полином. Таким образом, в рассматриваемой функции нас будет интересовать только старший член полинома без множителя (то есть ), как дающий наибольший вклад в сложность вычислений и называемый порядком роста (order of growth), или, как ещё говорят, скоростью роста (rate of growth) сложности вычислений.

Рассматривая входные данные достаточно больших размеров с целью получения оценки только лишь такой величины, как порядок роста времени работы алгоритма, мы тем самым изучаем асимптотическую эффективность алгоритмов. Это означает, что нас интересует только то, как время работы алгоритма растёт в пределе (то есть с увеличением размера входных данных до бесконечности).

В разделе математики, занимающимся анализом пределов (то есть бесконечно малых/больших величин) и называемом математическим анализом, для предельных величин существует специальное обозначение lim, что является сокращением от слова limit (на русский язык переводится какпредел):

  • - значение функции при , стремящемся к плюс бесконечности;
  • - значение функции при , стремящемся к минус бесконечности;
  • - значение функции при , стремящемся к нулю.

Таким образом, когда мы говорим, что изучаем асимптотическую эффективность алгоритма, то это означает, что нас интересует значение времени работы алгоритма при размере входных данных , стремящемся к плюс бесконечности, и это время мы можем записать как .

Обычно алгоритм, более эффективный в асимптотическом смысле, будет более производительным для всех входных данных, за исключением очень маленьких. Что это значит?

Представим, что у нас имеется два алгоритма, решающих одну и ту же задачу. Время работы первого алгоритма: . Время работы второго алгоритма: . Порядок роста сложности вычислений второго алгоритма равен и ниже порядка роста сложности вычислений первого алгоритма (). То есть второй алгоритм в асимптотическом смысле является более эффективным, чем первый алгоритм. Несмотря на то, что второй алгоритм эффективней первого, при малых значениях первый алгоритм будет выполняться быстрей второго алгоритма, например:

Однако, с ростом , второй алгоритм рано или поздно начнёт выполняться быстрей первого алгоритма, например:

Таким образом, при большом размере входных данных , порядок роста алгоритма будет играть ключевую роль в сложности вычислений, и в вычислениях будет выигрывать тот алгоритм, чей порядок роста ниже.

Исходя из всего выше сказанного, делаем вывод, что в любых алгоритмах, в первую очередь, нас интересует порядок роста сложности вычислений этих алгоритмов. Например, в случае полинома нас будет интересовать только старший член этого полинома.

Теперь рассмотрим конкретный пример: алгоритм поиска минимального элемента в массиве размерностью .

Поиск минимального элемента в массиве

a[0..n-1] = [k1, …, kn] // операций присваивания начальных значений в массив

res = // операция присваивания

for i = 0..n-1 // операции на итерацию: проверка, что i не превышает n-1, а также увеличение i на 1

res = min(res, a(i)) // операции на итерацию: сравнение; возврат результата из min() и его копирование в res

print(res) // операция вывода полученного минимального значения на экран


a[0..n-1] = [k1, …, kn] // операций

res = // операция

for i = 0..n-1 // операций, так как будет выполнено итераций,

// содержащих по 2 операции (сравнения и инкрементации),

// а в самом конце будет выполнена только одна операция

// сравнения, показывающая, что условие выхода из цикла

// достигнуто

res = min(res, a(i)) // операций

print(res) // операция

Время работы алгоритма:

Представленный алгоритм поиска минимального элемента в массиве никак не зависит от характера входных данных (данные могут быть как отсортированными в убывающем или возрастающем порядке, так и неотсортированными вовсе), то есть алгоритм работает одинаковым образом для всех возможных случаев входных данных. По этой причине полученная оценка для времени работы алгоритма также не зависит от характера входных данных, то есть времена работ для наихудшего и наилучшего случаев входных данных совпадают. Под наихудшим случаем входных данных подразумеваются вариант входных данных, для которого алгоритм решения поставленной задачи будет отрабатывать медленней всего. Соответственно, под наилучшим случаем входных данных подразумеваются вариант входных данных, для которого алгоритм решения поставленной задачи будет отрабатывать быстрей всего.

При очень большом значении параметра , в функции можно пренебречь:

  • слагаемым , как дающим наименьший вклад в сложность вычислений;
  • множителем 6 старшего члена полинома (), так как этот множитель является только оценкой, и реальное значение этого множителя может быть совсем иным.

Исходя из сказанного, можем сделать вывод, что - порядок роста сложности вычислений алгоритма поиска минимального элемента в массиве размерностью .



ВПЕРЁД

НАЗАД