Алгоритм Крускала [1] находит минимальный остовной лес неориентированного графа с рёберным весом . Если граф связный , он находит минимальное остовное дерево . Это жадный алгоритм , который на каждом шаге добавляет к лесу ребро с наименьшим весом, которое не образует цикл . [2] Ключевыми шагами алгоритма являются сортировка и использование структуры данных непересекающегося множества для обнаружения циклов. Время его работы определяется временем сортировки всех рёбер графа по их весу.
Минимальное остовное дерево связного взвешенного графа — это связный подграф без циклов, для которого сумма весов всех ребер в подграфе минимальна. Для несвязного графа минимальный остовный лес состоит из минимального остовного дерева для каждого связного компонента .
Этот алгоритм был впервые опубликован Джозефом Крускалом в 1956 году [3] и вскоре после этого был переоткрыт Лоберманом и Вайнбергером (1957). [4] Другие алгоритмы для этой задачи включают алгоритм Прима , алгоритм Борувки и алгоритм обратного удаления .
Алгоритм выполняет следующие шаги:
По завершении алгоритма лес образует минимальный остовной лес графа. Если граф связный, лес имеет один компонент и образует минимальное остовное дерево.
Следующий код реализован с использованием структуры данных непересекающегося множества . Он представляет лес F как набор ненаправленных ребер и использует структуру данных непересекающегося множества для эффективного определения того, являются ли две вершины частью одного и того же дерева.
Алгоритм Крускала ( G ) — это Ф:= ∅ для каждого v в GV сделать СДЕЛАТЬ-SET(v) для каждого {u, v} в GE, упорядоченном по весу ({u, v}), увеличивая do если FIND-SET(u) ≠ FIND-SET(v) тогда Ф := Ф ∪ { {u, v} } ОБЪЕДИНЕНИЕ(НАЙТИ-НАБОР(u), НАЙТИ-НАБОР(v)) возвращение F
Для графа с E ребрами и V вершинами можно показать, что алгоритм Краскала работает за время O ( E log E ) с простыми структурами данных. Здесь O выражает время в большой нотации O , а log является логарифмом по любому основанию (поскольку внутри O -нотации логарифмы по всем основаниям эквивалентны, потому что они одинаковы с точностью до постоянного множителя). Это ограничение по времени часто записывается как O ( E log V ) , что эквивалентно для графов без изолированных вершин, потому что для этих графов V /2 ≤ E < V 2 и логарифмы V и E снова находятся в пределах постоянного множителя друг от друга.
Чтобы достичь этой границы, сначала отсортируйте ребра по весу, используя сортировку сравнением за время O ( E log E ) . После сортировки можно выполнить цикл по ребрам в отсортированном порядке за постоянное время на ребро. Затем используйте структуру данных непересекающегося множества с набором вершин для каждого компонента, чтобы отслеживать, какие вершины находятся в каких компонентах. Создание этой структуры с отдельным набором для каждой вершины занимает V операций и O ( V ) времени. Окончательная итерация по всем ребрам выполняет две операции поиска и, возможно, одну операцию объединения на ребро. Эти операции занимают амортизированное время O ( α ( V )) на операцию, что дает наихудшее общее время O ( E α ( V )) для этого цикла, где α — чрезвычайно медленно растущая обратная функция Аккермана . Эта часть временной границы намного меньше времени для шага сортировки, поэтому общее время для алгоритма можно упростить до времени для шага сортировки.
В случаях, когда ребра уже отсортированы или имеют достаточно малый целочисленный вес, позволяющий алгоритмам целочисленной сортировки, таким как сортировка подсчетом или радиксная сортировка, сортировать их за линейное время, операции с непересекающимися множествами являются самой медленной оставшейся частью алгоритма, а общее время составляет O ( E α( V )) .
Доказательство состоит из двух частей. Во-первых, доказывается, что алгоритм создает остовное дерево . Во-вторых, доказывается, что построенное остовное дерево имеет минимальный вес.
Пусть будет связным, взвешенным графом и пусть будет подграфом , созданным алгоритмом. не может иметь цикл, так как по определению ребро не добавляется, если оно приводит к циклу. не может быть отсоединен, так как первое встреченное ребро, соединяющее два компонента , было бы добавлено алгоритмом. Таким образом, является остовным деревом .
Покажем, что следующее предложение P истинно по индукции : если F — множество ребер, выбранных на любом этапе алгоритма, то существует некоторое минимальное остовное дерево, содержащее F и ни одно из ребер, отклоненных алгоритмом.
Алгоритм Крускала по своей сути последовательный и его трудно распараллелить. Однако возможно выполнить начальную сортировку ребер параллельно или, в качестве альтернативы, использовать параллельную реализацию двоичной кучи для извлечения ребра с минимальным весом в каждой итерации. [5] Поскольку параллельная сортировка возможна по времени на процессорах, [6] время выполнения алгоритма Крускала можно сократить до O ( E α( V )), где α снова является обратной функцией однозначной функции Аккермана .
Вариант алгоритма Крускала, названный Filter-Kruskal, был описан Осиповым и др. [7] и лучше подходит для распараллеливания. Основная идея Filter-Kruskal заключается в разбиении ребер аналогично быстрой сортировке и отфильтровывании ребер, которые соединяют вершины одного дерева, чтобы снизить стоимость сортировки. Следующий псевдокод демонстрирует это.
функция filter_kruskal(G) если | GE| < kruskal_threshold: возвращает kruskal(G) ось = выбрать_случайный(GE) E ≤ , E > = раздел(GE, pivot) A = фильтр_крускал(E ≤ ) E > = фильтр(E > ) A = A ∪ filter_kruskal(E > ) вернуть Aфункция partition(E, pivot) равна E ≤ = ∅, E > = ∅ foreach (u, v) in E do if weight(u, v) ≤ pivot then E ≤ = E ≤ ∪ {(u, v)} else E > = E > ∪ {(u, v)} return E ≤ , E >функция filter(E) равна E f = ∅ foreach (u, v) in E do if find_set(u) ≠ find_set(v) then E f = E f ∪ {(u, v)} return E f
Фильтр-Крускал лучше поддается распараллеливанию, поскольку сортировка, фильтрация и разбиение могут легко выполняться параллельно путем распределения ребер между процессорами. [7]
Наконец, были исследованы другие варианты параллельной реализации алгоритма Крускала. Примеры включают схему, которая использует вспомогательные потоки для удаления ребер, которые определенно не являются частью MST в фоновом режиме, [8] и вариант, который запускает последовательный алгоритм на p подграфах, а затем объединяет эти подграфы, пока не останется только один, финальный MST. [9]
{{cite book}}
: CS1 maint: несколько имен: список авторов ( ссылка )