mafulechka25 июля 2019 г. 4:00

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

Содержание

Алгоритм Краскала - это алгоритм минимального остовного дерева, что принимает граф в качестве входных данных и находит подмножество ребер этого графа, который формирует дерево, включающее в себя каждую вершину, а также имеет минимальную сумму весов среди всех деревьев, которые могут быть сформированы из графа.

Как работает алгоритм Краскала

Он подпадает под класс алгоритмов, называемых «жадными» алгоритмами , которые находят локальный оптимум в надежде найти глобальный оптимум.

Мы начинаем с ребер с наименьшим весом и продолжаем добавлять ребра, пока не достигнем нашей цели.

Шаги для реализации алгоритма Краскала следующие:

  1. Сортировать все ребра от малого веса до высокого.
  2. Возьмите ребро с наименьшим весом и добавьте его в остовное дерево. Если добавление ребра создало цикл, то отклоните это ребро.
  3. Продолжайте добавлять ребра, пока не достигнете всех вершин.

Пример алгоритма Краскала

Алгоритм Краскала. Псевдокод.

Любой минимальный алгоритм остовного дерева вращается вокруг проверки, создает ли ребро цикл или нет.

Наиболее распространенный способ выяснить это - алгоритм Union FInd . Алгоритм Union-Find разделяет вершины на кластеры и позволяет нам проверить, принадлежат ли две вершины одному кластеру или нет, и, следовательно, решить создает ли добавление ребра цикл.

KRUSKAL(G):
A = ∅
For each vertex v ∈ G.V:
    MAKE-SET(v)
For each edge (u, v) ∈ G.E ordered by increasing order by weight(u, v):
    if FIND-SET(u) ≠ FIND-SET(v):       
    A = A ∪ {(u, v)}
    UNION(u, v)
return A

Реализация алгоритма Краскала в C ++

Ниже приведен код для реализации в C ++. Мы используем стандартные библиотеки шаблонов, чтобы сделать нашу работу проще и чище.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

#define edge pair<int,int>

class Graph {
private:
    vector<pair<int, edge>> G; // graph
    vector<pair<int, edge>> T; // mst
    int *parent;
    int V; // number of vertices/nodes in graph
public:
    Graph(int V);
    void AddWeightedEdge(int u, int v, int w);
    int find_set(int i);
    void union_set(int u, int v);
    void kruskal();
    void print();
};
Graph::Graph(int V) {
    parent = new int[V];

    //i 0 1 2 3 4 5
    //parent[i] 0 1 2 3 4 5
    for (int i = 0; i < V; i++)
        parent[i] = i;

    G.clear();
    T.clear();
}
void Graph::AddWeightedEdge(int u, int v, int w) {
    G.push_back(make_pair(w, edge(u, v)));
}
int Graph::find_set(int i) {
    // If i is the parent of itself
    if (i == parent[i])
        return i;
    else
        // Else if i is not the parent of itself
        // Then i is not the representative of his set,
        // so we recursively call Find on its parent
        return find_set(parent[i]);
}

void Graph::union_set(int u, int v) {
    parent[u] = parent[v];
}
void Graph::kruskal() {
    int i, uRep, vRep;
    sort(G.begin(), G.end()); // increasing weight
    for (i = 0; i < G.size(); i++) {
        uRep = find_set(G[i].second.first);
        vRep = find_set(G[i].second.second);
        if (uRep != vRep) {
            T.push_back(G[i]); // add to tree
            union_set(uRep, vRep);
        }
    }
}
void Graph::print() {
    cout << "Edge :" << " Weight" << endl;
    for (int i = 0; i < T.size(); i++) {
        cout << T[i].second.first << " - " << T[i].second.second << " : "
                << T[i].first;
        cout << endl;
    }
}
int main() {
    Graph g(6);
    g.AddWeightedEdge(0, 1, 4);
    g.AddWeightedEdge(0, 2, 4);
    g.AddWeightedEdge(1, 2, 2);
    g.AddWeightedEdge(1, 0, 4);
    g.AddWeightedEdge(2, 0, 4);
    g.AddWeightedEdge(2, 1, 2);
    g.AddWeightedEdge(2, 3, 3);
    g.AddWeightedEdge(2, 5, 2);
    g.AddWeightedEdge(2, 4, 4);
    g.AddWeightedEdge(3, 2, 3);
    g.AddWeightedEdge(3, 4, 3);
    g.AddWeightedEdge(4, 2, 4);
    g.AddWeightedEdge(4, 3, 3);
    g.AddWeightedEdge(5, 2, 2);
    g.AddWeightedEdge(5, 4, 3);
    g.kruskal();
    g.print();
    return 0;
}

Когда мы запускаем программу, мы получаем вывод как:

Edge : Weight
1 - 2 : 2
2 - 5 : 2
2 - 3 : 3
3 - 4 : 3
0 - 1 : 4

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

Алгоритм Прима является еще одним популярным алгоритмом минимального остовного дерева, который использует другую логику для нахождения MST графа. Вместо того, чтобы начинать с ребра, алгоритм Прима начинается с вершины и продолжает добавлять ребра с наименьшим весом, которых нет в дереве, пока все вершины не будут покрыты.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate

Я так понимаю, это перевод статьи?

Вот такие фразы выглядят стремно: "Любой минимальный алгоритм остовного дерева"
"популярным алгоритмом минимального остовного дерева"
Возможно, должно быть "алгоритмом построения ..."

Первое предложение тоже несогласованное.

Странной кажется идея запихивания графа в класс. Да и все равно можно выстрелить в ногу, вызвав print до вызова kruskal.

Не очевидна связь приведенного кода с описанным алгоритмом. - Что это за массив parent и почему (кстати) он не уничтожается в деструкторе?

Псевдокод не понятный. Что делает функция UNION(u, v) ?
Обе строки 7 и 8 вложены внутрь блока if?

У нормальной реализации алгоритма сложность N*log(N). А у вас для каждого узла графа вызывается функция find_set, которая имеет трудоемкость O(N). И того - O(N^2). Функция find_set при этом вообще особо кривая. Не понятно что она должна вернуть в каком случае.

Ну и еще, вот эта структура выглядит очень плохо:
vector > G;
Ну потому что edge - это тоже pair и в результате, во всех этих second.first и second.second хрен разберешься. Отрефакторить можно, например, введением нормальной структуры для дуги (вместо пары). При этом, в эту же дугу стоит засунуть длину. Легко ли въехать где тут номер дуги, а где - ее длина?

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
T

C++ - Тест 003. Условия и циклы

  • Результат:57баллов,
  • Очки рейтинга-2
TG

C++ - Тест 001. Первая программа и типы данных

  • Результат:53баллов,
  • Очки рейтинга-4
TG

C++ - Тест 001. Первая программа и типы данных

  • Результат:60баллов,
  • Очки рейтинга-1
Последние комментарии
t
  • t1m4
  • 23 января 2021 г. 8:28

Django - Урок 052. Переопределение модели пользователя

Добрый день, Я вот написал в admin.py admin.site.register(User, UserAdmin) Но у меня не появилось новые поля в админке?

Django - Урок 001. Развёртывание сайта на Django + PostgreSQL + Gunicorn + Nginx

Ошибка в конфиге инжинкса про статику в root последний слеш лишний путь в таком виде получается /home/user/myprojectenv/myproject/myproject//static

Qt/C++ - Урок 061. Добавление изображений в приложение методом Drag And Drop из файлового менеджера

// Вместо отрисовки иконки и текста будем отрисовывать только одно изображение // с небольшими отступами в 5 пикселей QPixmap pix(m_model->data(index).toString()); …
m
  • magrif
  • 19 января 2021 г. 12:37

Qt Сертификация

Здравствуйте. Подскажите, оплачивать ваучер прямо в выбранном тестовом центре? Можно ли загранник предъявить? Или свой паспорт, а заполнить транслитом? А то там пишут: Your name must exactl…
r
  • retmas
  • 17 января 2021 г. 4:09

Qt/C++ - Урок 074. Генерация псевдослучайных чисел с использованием случайной библиотеки STD

Дмитрий, решает. Просто автор, видимо, не сильно озаботился изучением документации QRandomGenerator. Да и в листинге с использованием qrand вызов функции qsrand на каждой итерации цикла нав…
Сейчас обсуждают на форуме
p

QScrollArea dynamically add QCheckBoxes

онлайн казино Пин Ап официальный сайт играть на деньги или бесплатно без регистрации
p

Как поменять шаг оси с числового формата на текстовый

онлайн казино Пин Ап официальный сайт играть на деньги или бесплатно без регистрации
S

Добавление данных в модель из textEdit

Котов писать жалко, да что поделать - приходится) Вот мне пока не шибко понятно как именно при внесении новых данных обновлять модель, как мне заставить TableView отображать обновленные дан…
ИП
T

AbstractListModel использование в нескольких элементах

Разобрался. Извиняюсь за беспокойство. Я просто не поставил "model." перед переменными. Делаю рефакторинг под abstractModel, раньше модель была в QML и как то прокатывала без этого. На железе уж…
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB