Обсудим еще одну характеристику алгоритма - его сложность. Развитие и совершенствование компьютерной техники повлекло за собой создание разнообразных алгоритмов, обеспечивающих решение многочисленных прикладных задач, причем даже для однотипных задач создавалось (и создается) много алгоритмов (программ). Подобные алгоритмы ранее были названы эквивалентными. Однако для практики недостаточно знать, что решение некоторой задачи на компьютере в принципе возможно (т.е. проблема алгоритмически разрешима). Исполнение любого алгоритма требует определенного объема памяти компьютера для размещения данных и программы, а также времени центрального процессора по обработке этих данных - эти ресурсы ограничены и, следовательно, правомочен вопрос об эффективности их использования. Таким образом, в самом широком смысле понятие эффективности связано со всеми вычислительными ресурсами, необходимыми для работы алгоритма. Однако обычно под «самым эффективным» понимается алгоритм, обеспечивающий наиболее быстрое получение результата, поскольку в практических ситуациях именно ограничения по времени часто являются доминирующим фактором, определяющим пригодность того или иного алгоритма. По этой причине далее будет обсуждаться именно временная сложность алгоритмов.
Время работы алгоритма удобно выражать в виде функции от одной переменной, характеризующей «размер» конкретной задачи, т.е. объем входных данных, необходимых для ее решения. Такой подход удобен, поскольку сравнительная сложность задач может оцениваться через ее размер. Поскольку описание задачи, предназначенной для решения посредством вычислительного устройства, можно рассматривать в виде слова конечной длины, представленной символами конечного алфавита, в качестве формальной характеристики размера задачи можно принять длину входного слова. Например, если стоит задача определения максимального числа в некоторой последовательности из n элементов, то и размер задачи будет n, поскольку любой вариант входной последовательности можно задать словом из п символов.
Времення сложность алгоритма - это функция, которая каждой входной длине слова п ставит в соответствие максимальное(для всех конкретных однотипных задач длиной п) время, затрачиваемое алгоритмом на ее решение.
При этом, безусловно, предполагается, что во всех задачах используется одинаковая схема кодирования входных слов.
Различные алгоритмы имеют различную временную сложность и выяснение того, какие из них окажутся достаточно эффективны, а какие нет, определяется многими факторами. Однако теоретики, занимающиеся разработкой и анализом алгоритмов, для сравнения эффективности алгоритмов предложили простой подход, позволяющий прояснить ситуацию. Речь идет о различии между полиномиальными и экспоненциальными алгоритмами.
Полиномиальным называется алгоритм, временная сложность которого выражается некоторой полиномиальной функцией размера задачи п.
Алгоритмы, времення сложность которых не поддается подобной оценке, называются экспоненциальными.
Различие между указанными двумя типами алгоритмов становятся особенно заметными при решении задач большого размера. Для сопоставления в табл. 7.2 приведены данные о времени решения задач различной сложности (данные взяты из книги М.Гэри, Д.Джонсона [15, с.20] и соответствуют состоянию развития вычислительной техники приблизительно двадцатилетней давности -это сказывается на абсолютных значениях времени обработки, но относительные показатели при этом не изменятся).
Из приведенных данных видно, что, во-первых, время обработки экспоненциальных алгоритмов при одинаковых размерах задач (превышающих 20) намного выше, чем у полиномиальных; во-вторых, скорость нарастания времени обработки с увеличением размера задачи у экспоненциальных алгоритмов значительно выше, чем у полиномиальных.
Различие между обоими типами алгоритмов проявляются еще более убедительно, если проанализировать влияние увеличения быстродействия компьютера на время исполнения алгоритма. В табл. 7.3 показано, насколько возрастают размеры наибольшей задачи, решаемой за единицу машинного времени, если быстродействие компьютера вырастет в 100 и 1000 раз.
Из табл. 7.3 видно, что, например, для экспоненциального алгоритма с функцией сложности f(n) = 2n рост скорости вычислений в 1000 раз приводит лишь к тому, что размер наибольшей задачи возрастает всего на 10 единиц, в то время как для функции f(n) = п5 она возрастает почти в 4 раза.
Таблица 7.2.
Таблица 7.3.
Приведенные примеры призваны показать, что подобно тому, как существуют алгоритмически неразрешимые задачи, существуют и задачи объективно сложные, т.е. такие, трудоемкость которых невозможно уменьшить совершенствованием компьютера. Задача считается труднорешаемой, если для нее не удается построить полиномиального алгоритма. Это утверждение не является категорическим, поскольку известны задачи, в которых достаточно эффективно работают и экспоненциальные алгоритмы. Примером может служить симплекс-метод, который успешно используется при решении задач линейного программирования, имея функцию сложности f(n) = 2n. Однако подобных примеров не очень много, и общей следует признать ситуацию, что эффективно исполняемыми можно считать полиномиальные алгоритмы с функциями сложности п, n2 или п3. Например, при решении задачи поиска нужного данного из п имеющихся в худшем варианте сложность равна п; если же оценить среднюю трудоемкость (продолжительность поиска), то она составит (п + 1)/2 - в обоих случаях функция сложности оказывается линейной п. Задача ранжирования, т.е. расстановки в заданном порядке п однотипных данных приводит к полиному 2-й степени; сложность задачи вычисления определителя системы п линейных уравнений с п неизвестными характеризуется полиномом 3-й степени. Повышение быстродействия элементов компьютера уменьшает время исполнения алгоритма, но не уменьшает степень полинома сложности. Следовательно, решению практической задачи на компьютере должна предшествовать оценка ее сложности и доказательство того, что задача решаема за приемлемое время.