Algorithm Improvement: Minimum Spanning Tree Algorithm for Graphs - Kruskal

Table of contents

concept

train of thought

the code


concept

The method of Kruskal's algorithm to find the minimum spanning tree is: sort all the edges in the connected network in ascending order according to the weight, and start to select the edge with the smallest weight, as long as this edge does not form a cycle with the selected edge , you can choose it to form a minimum spanning tree. For a connected network with N vertices, select N-1 edges that meet the conditions, and the spanning tree formed by these edges is the minimum spanning tree.

For example, Figure 1 is a connected network, and the Kruskal algorithm to find the minimum spanning tree corresponding to Figure 1 needs to go through the following steps:
 


Figure 1 Connected network


1) Sort all the edges in the connected network in ascending order according to the weight:
 


2) Start selection from the BD edge, since no edge has been selected to form a minimum spanning tree, and BD itself will not form a cycle, so the BD edge can form a minimum spanning tree.
 


Figure 2 BD edges form a minimum spanning tree


3) The DT edge will not form a loop with the selected BD edge, and can form a minimum spanning tree:
 


Figure 3 DT edges form a minimum spanning tree


4) The AC edge will not form a loop with the selected BD and DT edges, and can form a minimum spanning tree:
 


Figure 4 AC edges form a minimum spanning tree


5) The CD edge will not form a loop with the selected AC, BD, and DT edges, and can form a minimum spanning tree:
 


Figure 5 CD edge composition minimum spanning tree


6) The CB edge will form a loop with the selected CD and BD edges, so it cannot form a minimum spanning tree:
 


Figure 6 CB edges cannot form a minimum spanning tree


7) The three edges BT, AB, and SA will form a cycle with the selected AC, CD, BD, and DT, and none of them can form a minimum spanning tree. But SA will not form a loop with the selected edge, and can form a minimum spanning tree.
 


Figure 7 SA edges form a minimum spanning tree


8) As shown in Figure 7, for a connected network containing 6 vertices, we have selected 5 edges, and the spanning tree formed by these edges is the minimum spanning tree.
 


Figure 8 Minimum spanning tree

train of thought

In the whole K algorithm, in fact, it simply consists of two steps:

  1. find the shortest edge in the path;
  2. See if this edge will form a loop to the existing edge, if it does, discard it, if not, record it;

The difficulty is to judge whether there will be a ring. Here you can use the idea of ​​​​and search, or you can directly use a set to put all the nodes into the set. If the two nodes of the edge selected next time are in the set, you can If it is found, it means that it will cause a loop.

the code

#include <stdio.h>
#include <stdlib.h>
#define N 9   // 图中边的数量
#define P 6   // 图中顶点的数量
//构建表示边的结构体
struct edge {
    //一条边有 2 个顶点
    int initial;
    int end;
    //边的权值
    int weight;
};

//qsort排序函数中使用,使edges结构体中的边按照权值大小升序排序
int cmp(const void* a, const void* b) {
    return  ((struct edge*)a)->weight - ((struct edge*)b)->weight;
}
//克鲁斯卡尔算法寻找最小生成树,edges 存储用户输入的图的各个边,minTree 用于记录组成最小生成树的各个边
void kruskal_MinTree(struct edge edges[], struct edge minTree[]) {
    int i, initial, end, elem, k;
    //每个顶点配置一个标记值
    int assists[P];
    int num = 0;
    //初始状态下,每个顶点的标记都不相同
    for (i = 0; i < P; i++) {
        assists[i] = i;
    }
    //根据权值,对所有边进行升序排序
    qsort(edges, N, sizeof(edges[0]), cmp);
    //遍历所有的边
    for (i = 0; i < N; i++) {
        //找到当前边的两个顶点在 assists 数组中的位置下标
        initial = edges[i].initial - 1;
        end = edges[i].end - 1;
        //如果顶点位置存在且顶点的标记不同,说明不在一个集合中,不会产生回路
        if (assists[initial] != assists[end]) {
            //记录该边,作为最小生成树的组成部分
            minTree[num] = edges[i];
            //计数+1
            num++;
            elem = assists[end];
            //将新加入生成树的顶点标记全部改为一样的
            for (k = 0; k < P; k++) {
                if (assists[k] == elem) {
                    assists[k] = assists[initial];
                }
            }
            //如果选择的边的数量和顶点数相差1,证明最小生成树已经形成,退出循环
            if (num == P - 1) {
                break;
            }
        }
    }
}

void display(struct edge minTree[]) {
    int cost = 0, i;
    printf("最小生成树为:\n");
    for (i = 0; i < P - 1; i++) {
        printf("%d-%d  权值:%d\n", minTree[i].initial, minTree[i].end, minTree[i].weight);
        cost += minTree[i].weight;
    }
    printf("总权值为:%d", cost);
}

int main() {
    int i;
    struct edge edges[N], minTree[P - 1];
    for (i = 0; i < N; i++) {
        scanf("%d %d %d", &edges[i].initial, &edges[i].end, &edges[i].weight);
    }
    kruskal_MinTree(edges, minTree);
    display(minTree);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_32378713/article/details/128073869
Recommended