设计程序完成如下功能:对给定的图结构,实现求解最小生成树的Kruskal算法,并给出求解过程的动态演示
加入集合是说把结点加入,例如上图所示0,2,3在一个集合中
#include <stdio.h>
#include <stdlib.h>
typedef struct Edge {
int u, v, weight; // 边的起点、终点和权重
} Edge;
// 冒泡排序,用于排序边
void bubbleSortEdges(Edge edges[], int E) {
for (int i = 0; i < E - 1; i++) {
for (int j = 0; j < E - i - 1; j++) {
if (edges[j].weight > edges[j + 1].weight) {
Edge temp = edges[j];
edges[j] = edges[j + 1];
edges[j + 1] = temp;
}
}
}
}
// 查找节点的父节点
int find(int parent[], int x) {
while (parent[x] != -1) {
x = parent[x];
}
return x;
}
// 合并两个节点
void unionSets(int parent[], int u, int v) {
//代表u是v的父结点
parent[u] = v;
}
// Kruskal 算法
void kruskal(int V, Edge edges[], int E) {
// 初始化父节点数组
int *parent = malloc(V * sizeof(int));
for (int i = 0; i < V; i++) {
//-1代表没有父结点
parent[i] = -1;
}
// 使用冒泡排序对边进行排序
bubbleSortEdges(edges, E);
Edge mst[V - 1]; // 用于存储最小生成树的边
int e = 0; // 当前已添加的边数
printf("构建最小生成树的过程:\n");
for (int i = 0; i < E && e < V - 1; i++) {
int u = edges[i].u;
int v = edges[i].v;
// 查找 u 和 v 的根节点
int rootU = find(parent, u);
int rootV = find(parent, v);
// 如果根节点不同,说明没有形成环
if (rootU != rootV) {
//添加边到mst中
mst[e++] = edges[i];
//合并集合 合并顶点加入集合中
unionSets(parent, rootU, rootV);
printf("增加边 (%d-%d) 的权重为 %d\n", u, v, edges[i].weight);
}
}
if (e != V - 1) {
printf("创建失败,图不是连通的.\n");
} else {
printf("最小生成树的边:\n");
for (int i = 0; i < e; i++) {
printf("(%d-%d) 的权重为 %d\n", mst[i].u, mst[i].v, mst[i].weight);
}
}
free(parent); // 释放内存
}
int main() {
int V = 7; // 顶点数
Edge edges[] = {
{0, 1, 10}, {0, 2, 6}, {0, 3, 5},
{1, 3, 15}, {2, 3, 4},
{3, 4, 9}, {3, 5, 12},
{4, 5, 7}, {4, 6, 8},
{5, 6, 11}
};
int E = sizeof(edges) / sizeof(edges[0]); // 计算边数
kruskal(V, edges, E); // 调用 Kruskal 算法
return 0;
}