МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
ДОНСКОЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
Кафедра ПО ВТ и АС
УТВЕРЖДАЮ
Зав.каф. Р. А. Нейдорф
"______"________2011г.
ПОЯСНИТЕЛЬНАЯ ЗАПИСКА
К курсовой работе _Программирование и основы алгоритмизации___________
(наименование учебной дисциплины)
на тему: «Создание программы алгорима Прима» _____________________________
________________________________________________________________________
________________________________________________________________________
______________________________________________________________
Автор работы _______________Селезнёв Денис_______________________________
Специальность__________________Мехатроника______________________________
Обозначение курсовой работы ___________________ Группа___УМ21___________
Руководитель проекта____________________ ______________________________
(подпись) (Ф.И.О.)
Работа защищена _______________________ ______________________________
(дата) (оценка)
Члены комиссии ________________________ ______________________________
(подпись) (Ф.И.О)
________________________ ______________________________
(подпись) (Ф.И.О)
________________________ ______________________________
(подпись) (Ф.И.О)
Ростов-на-Дону
2011
Оглавление
Теоретическая часть 3
Каркас неориентированного графа 3
Алгоритм Прима 3
Свойства минимальных остовов 6
Текст программы. 8
Блок схема 10
Диаграмма Насси-Шнейдермана. 14
Список литературы: 16
Теоретическая часть Каркас неориентированного графа
Оптимальным каркасом взвешенного графа называется каркас, минимизирующий некоторую функцию от весов входящих в него ребер. Чаще всего в качестве такой функции выступает сумма весов ребер, реже — произведение. Оптимальный каркас еще называют кратчайшей связывающей сетью для данного графа. Задача о построении кратчайшей связывающей сети встречается в различных приложениях достаточно часто.
Задача об оптимальном каркасе.
Задача об оптимальном каркасе (стягивающем дереве) состоит в следующем. Дан обыкновенный граф G=(V,E) и весовая функция на множестве ребер u: V R. Вес множества X E определяется как сумма весов составляющих его ребер. Требуется в графе G найти каркас минимального веса. В этом разделе будем предполагать, что граф G связен, так что решением задачи всегда будет дерево. Для решения задачи об оптимальном каркасе известно несколько алгоритмов.
Алгоритм Прима
Этот алгоритм назван в честь американского математика Роберта Прима (Robert Prim), который открыл этот алгоритм в 1957 г. Впрочем, ещё в 1930 г. этот алгоритм был открыт чешским математиком Войтеком Ярником (Vojtěch Jarník). Кроме того, Эдгар Дейкстра (Edsger Dijkstra) в 1959 г. также изобрёл этот алгоритм, независимо от них.
Алгоритм Прима следует общей схеме алгоритма построения минимального остова. В этом алгоритме растущая часть остова представляет собой дерево (множество рёбер которого есть А). Формирование дерева начинается с произвольной корневой вершины r. На каждом шаге добавляется ребро наименьшего веса среди рёбер соединяющих вершины этого дерева с вершинами не из дерева. По следствию такие рёбра являются безопасными для А, так что в результате получается минимальный остов.
При реализации важно быстро выбирать лёгкое ребро. Алгоритм получает на вход связный граф G и корень r минимального покрывающего дерева. В ходе алгоритма все вершины, ещё не попавшие в дерево, хранятся в очереди с приоритетами. Приоритет вершины v определяется значением key[u], которое равно минимальному весу рёбер, соединяющих v с вершинами дерева А. (Если таких рёбер нет, полагаем key[V] = ). Поле [v] для вершин дерева указывает на родителя, а для вершины v Q указывает на вершину дерева, в которую ведёт ребро веса key[v] (одно из таких рёбер, если их несколько). Мы не храним множество А вершин строимого дерева явно; его можно восстановить как
A = {(v, [v]):v V \{r} \Q}.
В конец работы алгоритма очередь Q пуста, и множество
A = {(v, [v]):v V \{r}}.
есть множество ребер покрывающего дерева.
MST-PRIM(G,W,r)
1 Q V[G]
2 for для каждой вершины u Q
3 do key[u]
4 key[r] 0
5 [r] NIL
6 while Q
7do u EXTRACT-MIN(Q)
8for для каждой вершины v Adj[u]
9 do if v Q и w(u,v)<key[v]
10 then [v] u
11 key(v) w(u,v)
После исполнения строк 1-5 и первого прохода цикла в строках 6 - 11 дерево состоит из единственной вершины r, все остальные вершины находятся в очереди, и значение key[v] для них равно длине ребра из r в v или , если такого ребра нет (в первом случае [v] = r). Таким образом, выполнен описанный выше инвариант (дерево есть часть некоторого остова, для вершин дерева поле указывает на родителя, а для остальных вершин на "ближайшую" вершину дерева - вес ребра до неё хранится в key[v].
Время работы алгоритма Прима зависит от того, как реализована очередь Q.
Тривиальная реализация: алгоритмы за и
Если искать каждый раз ребро простым просмотром среди всех возможных вариантов, то асимптотически будет требоваться просмотр рёбер, чтобы найти среди всех допустимых ребро с наименьшим весом. Суммарная асимптотика алгоритма составит в таком случае , что в худшем случае есть , — слишком медленный алгоритм.
Этот алгоритм можно улучшить, если просматривать каждый раз не все рёбра, а только по одному ребру из каждой уже выбранной вершины. Для этого, например, можно отсортировать рёбра из каждой вершины в порядке возрастания весов, и хранить указатель на первое допустимое ребро (напомним, допустимы только те рёбра, которые ведут в множество ещё не выбранных вершин). Тогда, если пересчитывать эти указатели при каждом добавлении ребра в остов, суммарная асимптотика алгоритма будет , но предварительно потребуется выполнить сортировку всех рёбер за , что в худшем случае (для плотных графов) даёт асимптотику .
Случай плотных графов: алгоритм за
Подойдём к вопросу поиска наименьшего ребра с другой стороны: для каждой ещё не выбранной будем хранить минимальное ребро, ведущее в уже выбранную вершину.
Тогда, чтобы на текущем шаге произвести выбор минимального ребра, надо просто просмотреть эти минимальные рёбра у каждой не выбранной ещё вершины — асимптотика составит .
Но теперь при добавлении в остов очередного ребра и вершины эти указатели надо пересчитывать. Заметим, что эти указатели могут только уменьшаться, т.е. у каждой не просмотренной ещё вершины надо либо оставить её указатель без изменения, либо присвоить ему вес ребра в только что добавленную вершину. Следовательно, эту фазу можно сделать также за.
Таким образом, мы получили вариант алгоритма Прима с асимптотикой.