- •Министерство образования Российской Федерации
- •Содержание
- •1.2 Скорость роста функций
- •1.3 Анализ алгоритмов; время работы в лучшем, худшем случаях и в среднем
- •1.4 Типы данных, структуры данных и абстрактные типы данных
- •1.5 Динамические множества
- •2 Алгоритмы сортировок
- •2.1 Понятие внутренней и внешней сортировки
- •2.2 Сортировка вставками
- •2.3 Сортировка слиянием
- •2.3.1 Описание алгоритма
- •2.3.2 Анализ времени работы алгоритмов «разделяй и властвуй»
- •2.3.2 Анализ времени работы сортировки слиянием через рекуррентное соотношение
- •2.3.3 Анализ времени работы сортировки слиянием через геометрическую интерпретацию
- •2.4 Пирамидальная сортировка
- •2.4.1 Введение в алгоритм
- •2.4.2 Сохранение основного свойства кучи
- •2.4.3 Построение кучи
- •2.5 Быстрая сортировка
- •2.5.1 Введение в алгоритм
- •2.5.2 Описание
- •2.5.3 Разбиение массива
- •2.5.4 Особенности работы быстрой сортировки
- •2.6 Особенности реализации алгоритмов сортировки; сортировка за линейное время
- •2.6.1 Введение
- •2.6.2 Разрешающее дерево сортировки сравнениями
- •2.7 Цифровая сортировка
- •2.8 Сортировка вычерпыванием
- •2.8.1 Описание алгоритма
- •2.8.2 Вероятностный анализ времени работы сортировки вычерпыванием
- •2.8.3 Анализ времени работы сортировки вычерпыванием через геометрическую интерпретацию
- •2.9 Сортировка подсчетом
- •2.9.1 Описание алгоритма
- •2.9.2 Анализ времени работы
- •3 Элементарные и нелинейные структуры данных
- •3.1 Элементарные структуры: список, стек, очередь, дек
- •3.1.1 Список Линейный однонаправленный список
- •Линейный двунаправленный список
- •Двунаправленный список с фиктивными элементами
- •Циклические списки
- •Циклический однонаправленный список
- •Циклический двунаправленный список
- •3.1.2 Стек
- •3.1.3 Очередь
- •3.1.3 Дек
- •3.2 Нелинейные структуры данных
- •3.2.1 Представление корневых деревьев в эвм
- •Обходы деревьев
- •3.2.2 Двоичные деревья Спецификация двоичных деревьев
- •Реализация
- •Обходы двоичных деревьев
- •3.2.3 Двоичные деревья поиска Основные операции
- •Минимум и максимум
- •Следующий и предыдущий элементы
- •Добавление и удаление
- •Случайные деревья поиска
- •Оптимальные деревья поиска
- •4 Хеширование
- •4.1 Введение
- •4.2 Прямая адресация; таблицы с прямой адресацией
- •4.3 Хеш – таблицы; возникновение коллизий и их разрешение
- •Разрешение коллизий с помощью цепочек
- •Анализ хеширования с цепочками
- •4.4 Способы построения хеш – функций Выбор хорошей хеш-функции
- •Ключи как натуральные числа
- •Деление с остатком
- •Умножение
- •Универсальное хеширование
- •4.5 Открытая адресация; способы вычисления последовательности испробованных мест: линейная последовательность проб, квадратичная последовательность проб, двойное хеширование
- •Линейная последовательность проб
- •1 / (1 – )
- •5 Основные принципы разработки алгоритмов
- •5.1 Введение в теорию графов
- •5.1.1 Графы
- •5.1.2 Представление графов
- •5.2 Алгоритмы на графах: поиск в ширину, поиск в глубину
- •5.2.1 Поиск в ширину (волновой алгоритм)
- •5.2.2 Анализ поиска в ширину
- •5.2.3 Деревья поиска в ширину
- •5.2.4 Поиск в глубину
- •5.2.5 Анализ поиска в глубину
- •5.2.6 Свойства поиска в глубину
- •5.2.7 Классификация рёбер
- •5.3 Топологическая сортировка, задача о разбиении графа на сильно связанные компоненты
- •5.3.1 Топологическая сортировка
- •5.3.2 Сильно связные компоненты
- •5.4 Алгоритм построения минимального остовного дерева
- •5.4.1 Остовные деревья минимальной стоимости
- •5.4.2 Построение минимального покрывающего дерева
- •5.4.3 Алгоритмы Крускала и Пpимa
- •5.4.4 Алгоритм Крускала
- •5.4.5 Алгоритм Прима
- •5.5 Задача нахождения кратчайших путей на графах; алгоритм Флойда; алгоритм Дейкстры
- •5.5.1 Нахождение кратчайшего пути
- •5.5.2 Алгоритм Дейкстры
- •5.5.3 Алгоритм Флойда
- •5.6 Поиск с возвратом
- •5.6.1 Введение
- •5.6.2 Переборные алгоритмы
- •5.6.3 Метод ветвей и границ
- •5.6.4 Метод альфа-бета отсечения
- •5.6.5 Локальные и глобальные оптимальные решения
- •5.7 Метод декомпозиции ( «Разделяй и властвуй»)
- •5.7.1 «Ханойские башни»
- •5.8 Жадные алгоритмы и динамическое программирование
- •5.8.1 Задача о выборе заявок
- •5.8.2 Дискретная задача о рюкзаке
- •5.8.3 Непрерывная задача о рюкзаке
- •5.8.4 Числа Фибоначчи
- •5.8.5 Задача триангуляции многоугольника
- •5.8.6 Дп, жадный алгоритм или что-то другое?
5.2 Алгоритмы на графах: поиск в ширину, поиск в глубину
5.2.1 Поиск в ширину (волновой алгоритм)
Этот алгоритм поиска в графе также называют волновым алгоритмом из-за того, что обход графа идет по принципу распространения волны. Волна растекается равномерно во все стороны с одинаковой скоростью. На i-ом шаге будут помечены все вершины, достижимые за i ходов, если ходом считать переход из одной вершины в другую.
procedure WidthSearch(v: integer);
var
Delayed: array[1..n] of integer; {Очередь}
Count, {Хвост очереди}
Head: integer; {Голова очереди}
Current, j: integer;
begin
Count := 1; Head := 0; Delayed[Count] := v;
Visited[v] := true;
repeat
Head := Head +1; Current := Delayed[Head];
for каждой вершины y, смежной с Current do
if not Visited[y] then begin
Count := Count + 1;
Delayed[Count] := Graph[y];
Visited[y] := true;
end;
until Count = Head;
end;
begin
while есть непомеченные вершины do begin
v := любая непомеченная вершина;
WidthSearch(v);
end;
end.
Листинг 5.1 – Поиск в ширину
Листинг 5.2 – Поиск в ширину
Данный алгоритм может быть описан и так. Пусть задан граф G = (V, Е) и фиксирована начальная вершина (source vertex) s. Алгоритм поиска в ширину перечисляет все достижимые из s (если идти по рёбрам) вершины в порядке возрастания расстояния от s. Расстоя- нием считается длина (число рёбер) кратчайшего пути. В процессе поиска из графа выделяется часть, называемая «деревом поиска в ширину» с корнем s. Она содержит все достижимые из s вершины (и только их). Для каждой из них путь из корня в дереве поиска будет одним из кратчайших путей (из начальной вершины) в графе. Алгоритм применим и к ориентированным, и к неориентированным графам.
Название объясняется тем, что в процессе поиска мы идём вширь, а не вглубь (сначала просматриваем все соседние вершины, затем соседей соседей и т.д.).
Для наглядности мы будем считать, что в процессе работы алгоритма вер- шины графа могут быть белыми, серыми и чёрными. Вначале они все белые, но в ходе работы алгоритма белая вершина может стать серой, а серая – чёрной (но не наоборот). Повстречав новую вершину, алгоритм поиска красит её, так что окрашенные (серые или чёрные) вершины – это в точности те, которые уже обнаружены. Различие между серыми и чёрными вершинами используется алгоритмом для управления порядком обхода: серые вершины образуют «линию фронта», а чёрные – «тыл». Более точно, поддерживается такое свойство: если (и, v) Еи и чёрная, то v – серая или чёрная вершина. Таким образом, только серые вершины могут иметь смежные необнаруженные вершины.
Вначале дерево поиска состоит только из корня – начальной вершины s. Как только алгоритм обнаруживает новую белую вершину v, смежную с ранее найденной вершиной и, вершина v (вместе с ребром (u, v)) добавляется к де- реву поиска, становясь ребёнком (child) вершины и, а и становится родителем (parent) v. Каждая вершина обнаруживается только однажды, так что двух ро- дителей у неё быть не может. Понятия предка (ancestor) и потомка (descendant) определяются как обычно (потомки – это дети, дети детей, и т. д.). Двигаясь от вершины к корню, мы проходим всех её предков.
Приведённая ниже процедура BFS (breadth-first search – поиск в ширину) использует представление графа G = (V, Е) списками смежных вершин. Для каждой вершины и графа дополнительно хранятся её цвет color[u] и её пред- шественник [u]. Если предшественника нет (например, если и = s или и ещё не обнаружена), [u] = NIL. Кроме того, расстояние от s до и записывается в поле d[u]. Процедура использует также очередь Q(FIFO) для хранения множества серых вершин.
В строках 1 – 4 все вершины становятся белыми, все значения d бесконечны- ми, и родителем всех вершин объявляется NIL. Строки 5 – 8 красят вершину s в серый цвет и выполняют связанные с этим действия: в строке 6 расстояние d[s] объявляется равным 0, а в строке 7 говорится, что родителя у s нет. Наконец, в строке 8 вершина s помещается в очередь Q, и с этого момента очередь будет содержать все серые вершины и только их.
Основной цикл программы (строки 9 – 18) выполняется, пока очередь непус- та, то есть существуют серые вершины (вершины, которые уже обнаружены, но списки смежности которых ещё не просмотрены). В строке 10 первая такая вершина помещается в и. Цикл for в строках 11 – 16 просматривает все смежные с ней вершины. Обнаружив среди них белую вершину, мы делаем её серой (строка 13), объявляем и её родителем (строка 15) и устанавливаем расстояние равным d[u] + 1 (строка 14). Наконец, эта вершина добавляется в хвост очере- ди Q (строка 16). После этого уже можно удалить вершину и из очереди Q, перекрасив эту вершину в черный свет (строки 17 – 18).
Рисунок 5.1 – Поиск в ширину