#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_VERTEX 10//最多顶点个数
#define MAX_EDGE 100//最多边个数
typedef int DataType;
int findRoot(int *parent, int v);//函数声明
typedef struct EdgeType {
int from, to; //边依附的两个顶点
int weight;//边上的权值
} EdgeType;
struct EdgeGraph {
DataType vertex[MAX_VERTEX];//存放图顶点的数据
EdgeType edge[MAX_EDGE];//存放边的数组
int vertexNum, edgeNum; //图的顶点数和边数
};
void Graph(struct EdgeGraph *graph, int vertexNum, int arcNum) {
graph->edgeNum = arcNum;
graph->vertexNum = vertexNum;
printf("请逐个输入顶点的内容:");
DataType x;
for (int i = 0; i < vertexNum; i++) { //顶点数组赋值
scanf("%d", &x);
graph->vertex[i] = x;
}
int count = 1;
int a, b, ave;
for (int i = 0; i < arcNum; i++) { //依次输入每一条边
printf("请输入第%d条边依附的两个顶点的编号和权值:", count++);
scanf("%d %d %d", &a, &b, &ave); //输入该边依附的顶点的编号
graph->edge[i].from = a;
graph->edge[i].to = b;
graph->edge[i].weight = ave;
}
}
void ranklist(struct EdgeGraph *graph) { //将图的边数组按边的权值从小到大排序
EdgeType temp;
for (int i = 0; i < graph->edgeNum ; i++) { //冒泡排序
for (int j = 0; j < graph->edgeNum - i - 1; j++) {
if (graph->edge[j].weight > graph->edge[j + 1].weight) {
temp = graph->edge[j];
graph->edge[j] = graph->edge[j + 1];
graph->edge[j + 1] = temp;
}
}
}
}
void outputMST(EdgeType x) {
printf("(%d,%d)%d\n", x.from, x.to, x.weight);
}
void Kruskal(struct EdgeGraph graph, int *parent, int *sum) {
for (int i = 0; i < graph.vertexNum; i++)
parent[i] = -1; //初始化双亲数组,值为-1代表本身为根结点
int num, i, vex1, vex2;
for (num = 0, i = 0; i < graph.edgeNum; i++) {
vex1 = findRoot(parent, graph.edge[i].from); //找到所在生成树的根结点
vex2 = findRoot(parent, graph.edge[i].to); //找到所在生成树的根结点
if (vex1 != vex2) { //找到的两个根结点不同,不会构成环
outputMST(graph.edge[i]);//输出加入的边
*sum = *sum + graph.edge[i].weight; // 更新sum的值
parent[vex2] = vex1; //合成生成树
num++;
if (num == graph.vertexNum - 1) //循环了“图的顶点数-1”次,提前返回
return;
}
}
}
int findRoot(int *parent, int v) {
int t = v;
while (parent[t] > -1)
t = parent[t]; //求顶点t上的双亲直达根结点
return t;
}
void printGraph(struct EdgeGraph graph) {
printf(" no from to weight\n");
for (int i = 0; i < graph.edgeNum; i++) {
printf(" edge[%d] %d %d %d\n", i, graph.edge[i].from, graph.edge[i].to, graph.edge[i].weight);
}
}
main() {
int vertexNum, arcNum; //顶点个数,边的个数
printf("请输入顶点个数和边的个数:");
scanf("%d %d", &vertexNum, &arcNum);
struct EdgeGraph graph;
Graph(&graph, vertexNum, arcNum);
ranklist(&graph);
printf("输出通过边信息储存的图:\n");
printGraph(graph);
int parent[vertexNum];//每一个结点的双亲结点(根结点)
printf("输出Kruskal算法得的最小生成树(from,to)weght:\n");
int sum = 0; // 初始化sum为0
Kruskal(graph, parent, &sum); // 传入sum的地址
printf("sum 的值为:%d\n", sum); // 输出sum的值
//Kruskal(graph, parent);
}
Kruskal算法
最新推荐文章于 2024-10-09 22:28:58 发布