Алгоритм Прима

В информатике , алгоритм Прима — это жадный алгоритм который находит минимальное остовное дерево для взвешенного неориентированного графа . Это означает, что он находит подмножество ребер , образующее дерево , включающее каждую вершину , где общий вес всех ребер в дереве минимизирован. Алгоритм строит это дерево по одной вершине за раз из произвольной начальной вершины, на каждом этапе добавляя самое дешевое возможное соединение из дерева в другую вершину.
Алгоритм был разработан в 1930 году чешским математиком Войтехом Ярником. [ 1 ] а затем заново открыт и переиздан учёным-компьютерщиком Робертом Примом в 1957 году. [ 2 ] и Эдсгер В. Дейкстра в 1959 году. [ 3 ] Поэтому его еще иногда называют алгоритмом Ярника , [ 4 ] Алгоритм Прима–Ярника , [ 5 ] Алгоритм Прима – Дейкстры [ 6 ] или алгоритм DJP . [ 7 ]
Другие известные алгоритмы решения этой задачи включают алгоритм Крускала и алгоритм Борувки . [ 8 ] Эти алгоритмы находят минимальный остовный лес в возможно несвязном графе; Напротив, самая базовая форма алгоритма Прима находит только минимальные остовные деревья в связных графах. Однако, запуская алгоритм Прима отдельно для каждого связного компонента графа, его также можно использовать для поиска минимального остовного леса. [ 9 ] С точки зрения асимптотической временной сложности эти три алгоритма одинаково быстры для разреженных графов , но медленнее, чем другие, более сложные алгоритмы. [ 7 ] [ 6 ] Однако для достаточно плотных графов алгоритм Прима можно заставить работать за линейное время , удовлетворяя или улучшая временные ограничения для других алгоритмов. [ 10 ]

Описание
[ редактировать ]Алгоритм неформально можно описать как выполнение следующих шагов:
- Инициализируйте дерево одной вершиной, произвольно выбранной из графа.
- Вырастите дерево на одно ребро: из ребер, соединяющих дерево с вершинами, которых еще нет в дереве, найдите ребро с минимальным весом и перенесите его в дерево.
- Повторяйте шаг 2 (пока все вершины не окажутся в дереве).
Более подробно это можно реализовать, следуя приведенному ниже псевдокоду .
- Свяжите с каждой вершиной v графа число C [ v ] (самая дешевая стоимость соединения с v ) и ребро E [ v ] (ребро, обеспечивающее это самое дешевое соединение). Чтобы инициализировать эти значения, установите все значения C [ v ] на +∞ (или на любое число, превышающее максимальный вес ребра) и установите для каждого E [ v ] значение специального флага , указывающее, что нет ребра, соединяющего v с предыдущим. вершины.
- Инициализировать пустой лес F и набор Q вершин, которые еще не включены в F (изначально все вершины).
- Повторяйте следующие шаги, пока Q не станет пустым:
- Найдите и удалите вершину v из Q, имеющую минимально возможное значение C [ v ]
- Добавьте v к F
- Перебираем ребра vw, соединяя v с другими вершинами w . Для каждого такого ребра, если w по-прежнему принадлежит Q и vw имеет меньший вес, чем C [ w ], выполните следующие шаги:
- Установите C [ w ] на стоимость ребра vw
- Установите E [ w ] так, чтобы он указывал на ребро vw .
- Возврат F , который включает в себя соответствующие ребра в E
Как описано выше, начальная вершина алгоритма будет выбрана произвольно, поскольку первая итерация основного цикла алгоритма будет иметь набор вершин из Q , все из которых имеют одинаковый вес, и алгоритм автоматически запустит новое дерево в F , когда он завершает связующее дерево каждого связного компонента входного графа. Алгоритм можно изменить так, чтобы он начинался с любой конкретной вершины s, задав C [ s ] числом, меньшим, чем другие значения C (например, ноль), и его можно модифицировать так, чтобы он находил только одно связующее дерево, а не весь охватывающий лес (более точно соответствующий неформальному описанию), останавливаясь всякий раз, когда он встречает другую вершину, помеченную как не имеющую связанного ребра.
Различные варианты алгоритма отличаются друг от друга тем, как множество Q реализовано : в виде простого связного списка или массива вершин или в виде более сложной структуры данных очереди приоритетов . Такой выбор приводит к различиям во временной сложности алгоритма. В общем, приоритетная очередь будет быстрее находить вершину v с минимальными затратами, но повлечет за собой более дорогие обновления при изменении значения C [ w ].
Временная сложность
[ редактировать ]Временная сложность алгоритма Прима зависит от структур данных, используемых для графа, и от упорядочивания ребер по весу, что можно сделать с помощью очереди с приоритетами . В следующей таблице показаны типичные варианты:
Структура данных с минимальным весом ребра | Временная сложность (общая) |
---|---|
матрица смежности , поиск | |
двоичная куча и список смежности | |
Куча Фибоначчи и список смежности |
Простая реализация Prim, использующая матрицу смежности или графическое представление списка смежности и линейный поиск в массиве весов, чтобы найти ребро минимального веса для добавления, требует O (|V| 2 ) время работы. Однако это время работы можно значительно сократить, используя кучи для реализации поиска ребер минимального веса во внутреннем цикле алгоритма.
Первая улучшенная версия использует кучу для хранения всех ребер входного графа, упорядоченных по их весу. Это приводит к времени работы в худшем случае O(|E| log |E|). Но сохранение вершин вместо ребер может еще больше улучшить ситуацию. Куча должна упорядочивать вершины по наименьшему весу ребра, который соединяет их с любой вершиной частично построенного минимального остовного дерева (MST) (или бесконечности, если такого ребра не существует). Каждый раз, когда вершина v выбирается и добавляется в MST, операция уменьшения ключа выполняется для всех вершин w за пределами частичного MST, так что v соединяется с w , устанавливая ключ на минимум его предыдущего значения и стоимости ребра. из ( v , w ).
Используя простую структуру данных двоичной кучи , теперь можно показать, что алгоритм Прима работает за время O (|E| log |V|), где |E| — количество ребер, а |V| это количество вершин. Используя более сложную кучу Фибоначчи , это можно свести к O (|E| + |V| log |V|), что асимптотически быстрее , если граф достаточно плотный , чтобы |E| есть ω (|V|), а линейное время , когда |E| не ниже |V| журнал |В|. Для графов еще большей плотности (имеющих не менее |V| с ребра для некоторого c > 1), алгоритм Прима можно заставить работать за линейное время еще проще, используя d -арную кучу вместо кучи Фибоначчи. [ 10 ] [ 11 ]

Доказательство правильности
[ редактировать ]Пусть P — связный взвешенный граф . На каждой итерации алгоритма Прима должно быть найдено ребро, соединяющее вершину подграфа с вершиной вне подграфа. Поскольку P связен, к каждой вершине всегда будет путь. Выход Y алгоритма Прима представляет собой дерево , поскольку ребро и вершина, добавленные в дерево Y, связаны. Пусть Y 1 — минимальное остовное дерево графа P. Если Y 1 = Y , то Y — минимальное остовное дерево. В противном случае пусть e — первое ребро, добавленное при построении дерева Y , которого нет в дереве Y 1 , а V — множество вершин, соединенных ребрами, добавленными перед ребром e . Тогда один конец ребра e находится в множестве V , а другой — нет. Поскольку дерево Y 1 является остовным деревом графа P существует путь, , в дереве Y 1 соединяющий две конечные точки. Двигаясь по пути, он должен встретить ребро f, вершину из множества V с вершиной, которой нет в множестве V. соединяющее Теперь на итерации, когда ребро e было добавлено к дереву Y , ребро f также могло быть добавлено, и оно было бы добавлено вместо ребра. e, если его вес был меньше e , и поскольку ребро f не добавлялось, заключаем, что
Пусть дерево Y 2 — граф, полученный удалением ребра f и добавлением ребра e из дерева Y 1 к нему . Легко показать, что дерево Y 2 связно, имеет то же количество ребер, что и дерево Y 1 , а общий вес его ребер не больше, чем у дерева Y 1 , поэтому оно также является минимальным остовным деревом графа P и содержит ребро e добавленные до него при построении множества V. и все ребра , описанные выше, и в конечном итоге мы получим минимальное остовное дерево графа P , идентичное дереву Y. Повторите шаги , Это показывает, что Y — минимальное остовное дерево. Минимальное связующее дерево позволяет расширить первое подмножество субрегиона до большего подмножества X , которое мы считаем минимальным.
Параллельный алгоритм
[ редактировать ]
Основной цикл алгоритма Прима по своей сути является последовательным и, следовательно, не поддается распараллеливанию . Однако внутренний цикл , определяющий следующее ребро минимального веса, не образующее цикл, можно распараллелить, разделив вершины и ребра между доступными процессорами. [ 12 ] Следующий псевдокод демонстрирует это.
- Назначьте каждый процессор набор последовательных вершин длины .
- Создайте C, E, F и Q, как в последовательном алгоритме , и разделите C, E, а также граф между всеми процессорами так, чтобы каждый процессор удерживал входящие ребра в свой набор вершин. Позволять , обозначают части C , E, хранящиеся в процессоре .
- Повторяйте следующие шаги, пока Q не станет пустым:
- На каждом процессоре: найдите вершину имеющий минимальное значение в [ ] (локальное решение).
- Минимизируйте локальные решения, чтобы найти вершину v , имеющую минимально возможное значение C [ v ] (глобальное решение).
- Трансляция выбранного узла на каждый процессор.
- Добавьте v к F и, если E [ v ] не является значением специального флага, также добавьте E [ v ] к F .
- На каждом процессоре: обновить и как в последовательном алгоритме.
- Возврат Ф
Этот алгоритм обычно может быть реализован на распределенных машинах. [ 12 ] а также на машинах с общей памятью. [ 13 ] Время работы , предполагая, что операции сокращения и трансляции могут выполняться в . [ 12 ] Также был исследован вариант алгоритма Прима для машин с общей памятью, в котором последовательный алгоритм Прима выполняется параллельно, начиная с разных вершин. [ 14 ] Однако следует отметить, что существуют более сложные алгоритмы для распределенного минимального остовного дерева более эффективного решения проблемы .
См. также
[ редактировать ]- Алгоритм Дейкстры , очень похожий алгоритм решения задачи о кратчайшем пути.
- Гридоиды предлагают общий способ понять правильность алгоритма Прима.
Ссылки
[ редактировать ]- ^ Ярник В. (1930), «О некоторой минимальной проблеме», Труды Моравского общества естественных наук (на чешском языке), 6 (4): 57–63, hdl : 10338.dmlcz/500726 .
- ^ Прим, Р.К. (ноябрь 1957 г.), «Кратчайшие сети соединений и некоторые обобщения» , Bell System Технический журнал , 36 (6): 1389–1401, Бибкод : 1957BSTJ...36.1389P , doi : 10.1002/j.1538-7305.1957. tb01515.x .
- ^ Дейкстра, Э.В. (декабрь 1959 г.), «Заметка о двух проблемах, связанных с графами» (PDF) , Numerische Mathematik , 1 (1): 269–271, CiteSeerX 10.1.1.165.7577 , doi : 10.1007/6013 , SBIDC0938 123284777 .
- ^ Седжвик, Роберт ; Уэйн, Кевин Дэниел (2011), Алгоритмы (4-е изд.), Аддисон-Уэсли, стр. 628, ISBN 978-0-321-57351-3 .
- ^ Розен, Кеннет (2011), Дискретная математика и ее приложения (7-е изд.), McGraw-Hill Science, стр. 798 .
- ^ Перейти обратно: а б Черитон, Дэвид ; Тарьян, Роберт Эндре (1976), «Нахождение минимальных остовных деревьев», SIAM Journal on Computing , 5 (4): 724–742, doi : 10.1137/0205051 , MR 0446458 .
- ^ Перейти обратно: а б Петти, Сет; Рамачандран, Виджая (январь 2002 г.), «Оптимальный алгоритм минимального остовного дерева» (PDF) , Журнал ACM , 49 (1): 16–34, CiteSeerX 10.1.1.110.7670 , doi : 10.1145/505241.505243 , MR 2148431 , S2CID 5362916 .
- ^ Тарьян, Роберт Эндре (1983), «Глава 6. Минимальные остовные деревья. 6.2. Три классических алгоритма», Структуры данных и сетевые алгоритмы , Серия региональных конференций CBMS-NSF по прикладной математике, том. 44, Общество промышленной и прикладной математики , стр. 72–77 .
- ^ Кепнер, Джереми; Гилберт, Джон (2011), Алгоритмы графов на языке линейной алгебры , программное обеспечение, среда и инструменты, том. 22, Общество промышленной и прикладной математики , с. 55, ISBN 9780898719901 .
- ^ Перейти обратно: а б Тарьян (1983) , с. 77.
- ^ Джонсон, Дональд Б. (декабрь 1975 г.), «Приоритетные очереди с обновлением и поиском минимальных связующих деревьев», Information Processing Letters , 4 (3): 53–57, doi : 10.1016/0020-0190(75)90001-0 .
- ^ Перейти обратно: а б с Грама, Анант; Гупта, Аншул; Карипис, Георгий; Кумар, Випин (2003), Введение в параллельные вычисления , стр. 444–446, ISBN 978-0201648652
- ^ Куинн, Майкл Дж.; Део, Нарсингх (1984), «Алгоритмы параллельных графов», ACM Computing Surveys , 16 (3): 319–348, doi : 10.1145/2514.2515 , S2CID 6833839
- ^ Сетия, Рохит (2009), «Новый параллельный алгоритм для решения задачи минимального остовного дерева» (PDF) , Proc. Международная конференция по высокопроизводительным вычислениям (HiPC)
Внешние ссылки
[ редактировать ]- Алгоритм Прима прогрессирует в случайно распределенных точках
СМИ, связанные с алгоритмом Прима, на Викискладе?