- •Содержание
- •Введение.
- •1. Основы анализа алгоритмов
- •1.1. Сравнительные оценки алгоритмов
- •1.2. Элементарные операции в формальной системе
- •1.3. Классы входных данных
- •1.4. Классификация алгоритмов по виду функции трудоемкости
- •1.5. Классификация скоростей роста. Асимптотический анализ функций
- •1. Оценка (тета)
- •2. Оценка о (о большое)
- •3. Оценка (Омега)
- •1.6. Эффективность рекурсивных алгоритмов
- •1.7. Анализ программ
- •1.8. Вопросы для самоконтроля
- •Классификация алгоритмов по виду функции трудоемкости.
- •2. Алгоритмы поиска и выборки
- •2.1. Последовательный поиск
- •2.2. Двоичный поиск
- •2.3. Задача выборки
- •2.4. Вопросы для самоконтроля
- •3.Алгоритмы сортировки
- •3.1. Сортировка трех чисел по месту
- •3.2. Сортировка вставками
- •3.3. Пузырьковая сортировка
- •3.4. Сортировка Шелла.
- •3.5. Корневая сортировка
- •3.6. Сортировка методом индексов
- •3.7. Быстрая сортировка (алгоритм Хоара)
- •3.8. Вопросы для самоконтроля
- •Сортировка Шелла.
- •Сортировка методом индексов.
- •4. Алгоритмы на графах
- •4.1. Основные понятия теории графов
- •4.2. Структуры данных для представления графов
- •4.3. Алгоритмы обхода вершин графа
- •4.3.1. Обход в глубину
- •4.3.2. Обход в ширину
- •4.4. Поиск остовного дерева минимального веса
- •4.4.1. Алгоритм Дейкстры – Прима
- •4.4.2. Алгоритм Крускала
- •4.5. Алгоритм поиска кратчайшего пути
- •4.6. Вопросы для самоконтроля
- •Структуры данных для представления графов.
- •5. Численные методы
- •5.1. Вычисление значений многочленов
- •5.2. Умножение матриц
- •5.2.1 Стандартный алгоритм умножения матриц
- •5.2.2. Умножение матриц по Винограду
- •5.2.3. Умножение матриц по Штрассену
- •5.3. Вопросы для самоконтроля
- •Стандартный алгоритм умножения матриц.
- •6. Алгоритмы сравнения с образцами
- •6.1. Сравнение строк
- •6.2. Алгоритм Кнута – Морриса – Пратта
- •6.3. Алгоритм Бойера - Мура
- •6.4. Вопросы для самоконтроля
- •7. Вычислительная геометрия
- •7.1. Основные понятия
- •7.2. Векторное произведение векторов
- •7.2.1. Ориентированная площадь треугольника
- •7 .3. Задача о выпуклой оболочке
- •7.3.1. Алгоритм Грэхема
- •7.3.2. Алгоритм Джарвиса
- •7.3.3. Рекурсивный алгоритм
- •7.4. Вопросы для самоконтроля
- •8. Задачи класса np
- •8.1. Примеры np-полных задач
- •8.1.1. Задача о коммивояжере
- •8.1.2. Задача о раскраске графа
- •8.1.3. Раскладка по ящикам
- •8.1.4 Упаковка рюкзака
- •8.1.5. Задача о суммах элементов подмножества
- •8.1.6. Задача о планировании работ
- •8.2. Приближенные эвристические решения nр-полных задач.
- •8.2.1. Жадные приближенные алгоритмы
- •8.2.2. Приближения в задаче коммивояжера
- •8.2.3. Приближения в задаче о раскладке по ящикам
- •8.2.4. Приближения в задаче об упаковке рюкзака
- •8.3. Вопросы для самопроверки
- •Приближения в задаче об упаковке рюкзака.
- •9. Динамическое программирование
- •Часть1--------------------
- •10. Метод ветвей и границ
- •Вопросы к зачету
- •Классификация алгоритмов по виду функции трудоемкости.
- •Приближения в задаче об упаковке рюкзака.
- •Динамическое программирование
- •Метод ветвей и границ. Литература
1.3. Классы входных данных
Роль входных данных в анализе алгоритмов чрезвычайно важна, так как последовательность действий алгоритма определяется не в последнюю очередь его входными данными.
Пример 1.3. Найти максимальный элемент в списке А из N элементов.
Max(A, N)
maxa[1]
for i=2 to N do
If max<a[i]
then maxa[i]
endif
endfor
end
Очевидно, что если список упорядочен в порядке убывания, то перед началом цикла будет сделано 1 присваивание, а в теле цикла – присваиваний не будет. Если список упорядочен по возрастанию, то всего будет сделано N присваиваний (одно – до цикла, и (N-1) – в цикле).
При анализе трудоемкости алгоритма в среднем должны быть рассмотрены различные множества входных значений, поскольку, если мы ограничимся одним множеством, оно может оказаться тем самым, на котором решение самое быстрое (или самое медленное). В результате мы получим ложное представление о трудоемкости алгоритма.
В этом случае необходимо разбить различные входные множества на классы в зависимости от поведения алгоритма на каждом множестве. Такое разбиение позволяет уменьшить количество рассматриваемых возможностей.
Пусть, например, наш список состоит из 10 чисел. Число различных расстановок 10 чисел в списке равно 10!=3 628 800.
Применим к списку из 10 чисел вышеприведенный алгоритм поиска максимального элемента. Имеется 362 880 входных множеств, у которых первое число является наибольшим; их все можно поместить в первый класс (1 присваивание и 9 сравнений).
Если наибольшее по величине число стоит на втором месте, то алгоритм сделает 2 присваивания и 9 сравнений. Таких множеств тоже 362 880. Их можно отнести к другому классу.
Таким образом, мы должны разбить все входное множество на 10 классов по числу сделанных присваиваний. Нет необходимости выписывать или описывать детально все множества, помещенные в каждый класс. Нужно знать лишь количество классов и объем работы алгоритма на каждом классе входных данных.
Если классы выбраны правильно, то на всех множествах входных данных одного класса алгоритм производит одинаковое количество операций; а на множествах из другого класса это количество операций, скорее всего, будет другим.
Не стоит ограничиваться анализом поведения алгоритма на одном входном наборе данных. Необходимо попытаться найти такие данные, которые обеспечивали бы самое быстрое и самое медленное выполнение алгоритма.
Следовательно, необходимо оценивать среднюю трудоемкость алгоритма на всех возможных наборах данных.
Введем специальные формальные обозначения, отражающие поведение функции трудоемкости данного алгоритма на входных данных фиксированной длины.
Пусть DА – множество конкретных проблем данной задачи, заданное в формальной системе. Пусть D DА – задание конкретной проблемы и |D| = N.
В общем случае существует собственное подмножество множества DА, включающее все конкретные проблемы, имеющие мощность N:
обозначим это подмножество через DN : DN = {D DN,: |D| = N};
обозначим мощность множества DN через MDN → MDN = |DN |.
Как было отмечено выше, некоторый алгоритм, решая различные задачи размерности N, будет выполнять в каком-то случае наибольшее количество операций, а в каком-то случае наименьшее количество операций. Ведем следующие обозначения:
1. fА (N) – худший случай – наибольшее количество операций, совершаемых алгоритмом А для решения конкретных проблем размерностью N:
DDN
Анализ наихудшего случая чрезвычайно важен, поскольку он позволяет представить максимальное время работы алгоритма. Анализ наихудшего случая дает верхние оценки для времени работы программы.
Например, для алгоритма последовательного поиска худший случай состоит в том, что или список с искомой информацией на последнем месте, или вообще ее нет.
2. fА (N) – лучший случай – наименьшее количество операций, совершаемых алгоритмом А для решения конкретных проблем размерностью N:
F
DDN
Например, если исследуется алгоритм последовательного поиска, то наилучшим набором данных является тот, в котором искомое значение записано в первой проверяемой ячейке. Такому алгоритму вне зависимости от его сложности, потребуется одно сравнение.
Наилучший случай требует, как правило, постоянного времени. Обычно это время оказывается незначительным или константным, поэтому этот случай отдельно анализируется редко.
3. fА (N) – средний случай – среднее количество операций, совершаемых алгоритмом А для решения конкретных проблем размерностью N:
DDN
Средний случай является самым сложным, поскольку он требует учета множества разнообразных деталей. Отметим одну из методик анализа, в основе которой лежит определение различных групп, на которые следует разбивать возможные входные наборы данных. На втором шаге определяется вероятность, с которой входной набор данных принадлежит каждой группе. На третьем шаге подсчитывается количество операций алгоритма для данных из каждой группы. (Количество операций на всех входных данных одной группы должны быть одинаковым.)
Среднее количество операций в этом случае определяется по формуле
fА (N) = , где
N – размер входных данных;
m – число групп;
pi – вероятность того, что входные данные принадлежат группе i;
ti - количество операций алгоритма («время») для обработки данных из группы с номером i.
В некоторых случаях мы будем предполагать, что вероятности попадания входных данных в каждую из групп одинаковы (1/m).
Упрощенная формула среднего случая
fА (N)= .
Вернемся к задаче поиска максимального значения из 3-х чисел (пример 1.1), и определим оценки трудоемкости алгоритма для различных классов входных данных.
MaxABC1(a,b,c) max a if b>max then maxb endif if c>max then maxc endif return (max) end |
MaxABC2(a,b,c) if a>b then if a>c then maxa else maxc endif else if b>c then maxb else maxc endif endif return (max) end
|
Для алгоритма MaxABC1 в худшем случае, если c>b>a, получаем fА1 =5 (2 сравнения и 3 присваивания). В лучшем случае, если значение (a) является максимумом, имеем: fА1=3 (2 сравнения и 1 присваивание). В среднем случае количество выполняемых действий будет равно:
fА1-=P1* f(1,2,3)+P2*f(1,3,2)+P3*f(2,1,3)+P4*f(2,3,1)+P5*f(3,1,2)+P6*f(3,2,1).
Очевидно, что если исходные значения приходят случайным образом, то вероятности Pi появления комбинаций (1,2,3),(1,3,2),(2,1,3),(2,3,1) (3,1,2),(3,2,1) будут равны между собой, то есть Pi = .Тогда получаем
fА 1=(5+4+4+4+3+3)=3.
Для алгоритма MaxABC2 функция трудоёмкости не зависит от тройки полученных чисел, и всегда будет одинакова: fА 2= fА 2=fА 2=3. Этот алгоритм является глобально эффективным.