Menu
Coddy logo textTech

Алгоритм Краскала

Последнее обновление

Алгоритм Краскала строит минимальное остовное дерево (MST) - самый дешёвый набор рёбер, соединяющий все вершины без циклов. Он сортирует все рёбра по весу, а затем жадно добавляет следующее самое дешёвое ребро, если оно соединяет две ещё не связанные вершины. Нажмите «воспроизвести» выше, чтобы увидеть, как дерево растёт, по одному безопасному дешёвому ребру за раз.

Проверка «уже связаны?» выполняется с помощью структуры данных union-find (система непересекающихся множеств): ребро пропускается, если оба его конца уже находятся в одной компоненте, потому что его добавление образовало бы цикл. Сортировка доминирует в стоимости, давая O(E log E) в целом. Краскал хорош на разреженных графах.

Временная и пространственная сложность

МераСложностьПримечания
ВремяO(E log E)Определяется сортировкой рёбер
Операции union-find≈ O(E α(V))Почти константа на проверку при сжатии путей
ПамятьO(V + E)Список рёбер + структура непересекающихся множеств
Лучше всего дляРазреженных графовРаботает из глобального списка рёбер

Пошагово

ШагЧто происходит
1Отсортировать каждое ребро по весу, по возрастанию.
2Поместить каждую вершину в собственную компоненту (union-find).
3Взять следующее самое дешёвое ребро.
4Если его концы в разных компонентах, добавить его в дерево и объединить их.
5Иначе пропустить его (оно создало бы цикл).
6Остановиться, когда в дереве V − 1 рёбер.

Разобранный пример

Граф с вершинами A, B, C, D и рёбрами A-B(1), B-C(2), A-C(3), C-D(4), B-D(5). Отсортированные рёбра: A-B(1), B-C(2), A-C(3), C-D(4), B-D(5):

Ребро (вес)Компоненты доДействие
A-B(1){A} {B} {C} {D}Разные компоненты - добавить в MST, объединить в {A,B}.
B-C(2){A,B} {C} {D}Разные компоненты - добавить в MST, объединить в {A,B,C}.
A-C(3){A,B,C} {D}A и C уже вместе - пропустить (образовало бы цикл).
C-D(4){A,B,C} {D}Разные компоненты - добавить в MST, объединить в {A,B,C,D}.
Стоп{A,B,C,D}В дереве V - 1 = 3 рёбер. MST = A-B, B-C, C-D, суммарный вес 7.

Когда использовать алгоритм Краскала

Используйте, когдаИзбегайте, когда
Граф разреженный (мало рёбер относительно вершин).Граф плотный - Прим с кучей обычно быстрее.
Рёбра уже доступны как глобальный список, который можно отсортировать.Рёбра приходят только через списки смежности, которые нужно обходить по вершинам.
Нужна простая реализация на основе union-find.Нужно, чтобы дерево росло из конкретной стартовой вершины.
Нужно построить остовный лес несвязного графа.Нужно обрабатывать рёбра в потоке без полной сортировки.

Код Kruskal's Algorithm

Чистая, готовая к запуску реализация Kruskal's Algorithm на Python, JavaScript, Java, C++, C. Выберите язык, скопируйте код или откройте его уже загруженным в плейграунде Coddy.

Код Kruskal's Algorithm на Python

Python
1def find(parent, x):2    while parent[x] != x:3        parent[x] = parent[parent[x]]  # path compression4        x = parent[x]5    return x6
7
8def kruskal(vertices, edges):9    # Take the cheapest edge that does not close a cycle10    parent = {v: v for v in vertices}11    mst, total = [], 012    for w, u, v in sorted(edges):13        root_u, root_v = find(parent, u), find(parent, v)14        if root_u != root_v:15            parent[root_u] = root_v16            mst.append((u, v, w))17            total += w18    return mst, total19
20
21vertices = ["A", "B", "C", "D", "E"]22edges = [23    (4, "A", "B"), (1, "A", "C"), (3, "B", "C"), (2, "B", "D"),24    (5, "C", "D"), (6, "C", "E"), (7, "D", "E"),25]26
27mst, total = kruskal(vertices, edges)28for u, v, w in mst:29    print(f"{u} - {v} (weight {w})")30print("Total MST weight:", total)
Запустите этот код в плейграунде Python

Часто задаваемые вопросы об алгоритме Краскала

Что такое минимальное остовное дерево?
Минимальное остовное дерево (MST) связного взвешенного графа - это подмножество рёбер, соединяющее все вершины без циклов и с наименьшим возможным суммарным весом. Оно имеет ровно V - 1 рёбер для V вершин.
В чём разница между алгоритмами Краскала и Прима?
Оба строят минимальное остовное дерево жадно. Краскал сортирует все рёбра глобально и добавляет самое дешёвое, не образующее цикл, используя union-find. Прим наращивает одно дерево наружу от стартовой вершины, всегда добавляя самое дешёвое ребро, выходящее из дерева. Краскал подходит для разреженных графов; Прим (с кучей) - для плотных.
Почему алгоритм Краскала использует union-find?
Перед добавлением ребра Краскал должен проверить, связаны ли уже оба его конца - добавление такого ребра создало бы цикл. Union-find (система непересекающихся множеств) отвечает на вопрос «в одной ли они компоненте?» и объединяет компоненты за почти константное амортизированное время, что сохраняет эффективность алгоритма.
Когда стоит использовать алгоритм Краскала вместо Прима?
Предпочитайте Краскал, когда граф разреженный и у вас уже есть все рёбра в виде списка, который можно отсортировать - сортировка O(E log E) дешева при малом E. Алгоритм Прима с двоичной или фибоначчиевой кучей обычно выигрывает на плотных графах, где E приближается к , так как избегает предварительной сортировки всех рёбер.
Работает ли алгоритм Краскала на несвязных графах?
Да. Если граф несвязный, Краскал просто не может достичь V - 1 рёбер и вместо этого строит минимальный остовный лес - по одному MST на каждую компоненту связности. Это получается естественно, потому что union-find никогда не объединяет вершины, между которыми нет пути.
Какая самая распространённая ошибка при реализации алгоритма Краскала?
Пропуск сжатия путей и объединения по рангу в union-find, из-за чего каждая проверка связности падает с почти константной до почти линейной и может доминировать во времени выполнения. Другая частая ошибка - забыть фактически объединить две компоненты после добавления ребра, что позволяет последующим рёбрам создавать циклы.
Coddy programming languages illustration

Освойте алгоритмы с Coddy

НАЧАТЬ