Kruskal
步骤: 1.将图转化为边表。 2.按权值排序边表。 3.初始化parent[孩子]=父亲。 4.依次找边。 5.找到最小权值边两顶点的最小孩子。 6.比较最小孩子,相等则形成环。 7.不相等则把结点存入树中,防止重复访问。
#include<stdio.h> #include<stdlib.h> #define MAXEDGE 99 #define MAXVEX 999 #define INFINITY 65535 typedef int VertexType; typedef int EdgeType; typedef struct MGraph { int numEdges, numNodes; VertexType vexs[MAXVEX]; EdgeType arc[MAXEDGE][MAXEDGE]; }MGraph; void CreatMGraph(MGraph* G) { int i, j, k, w; printf("请输入顶点数和边数:\n"); scanf("%d%d", &G->numNodes, &G->numEdges); printf("请输入顶点数据:\n"); for (i = 0; i < G->numNodes; i++) { scanf("%d", &G->vexs[i]); } for (i = 0; i < G->numNodes; i++) { for (j = 0; j < G->numNodes; j++) { G->arc[i][j] = INFINITY; } } printf("请输入权值数据:\n"); for (k = 0; k < G->numEdges; k++) { scanf("%d%d%d", &i, &j, &w); G->arc[i][j] = w; G->arc[j][i] = w; } } void PrintMGraph(MGraph* G) { int i,j; for (i = 0; i < G->numNodes; i++) { printf(" %d", G->vexs[i]); } printf("\n"); for (i = 0; i < G->numNodes; i++) { printf("%d", G->vexs[i]); for (j = 0; j < G->numNodes; j++) { if (G->arc[i][j] == INFINITY) { printf(" ∞"); } else { printf("%5d", G->arc[i][j]); } } printf("\n"); } } //矩阵图的边集结构 typedef struct { int begin;//边起始顶点 int end;//边终止顶点 int weight;//边的权值 }Edge[MAXEDGE]; //矩阵图转为边集数组 void ChangeGtoE(MGraph* G,Edge *edge) { int k=0, i, j; for (i = 0; i < G->numNodes; i++) { for (j = 0; j < G->numNodes; j++) { edge[k]->begin = i; edge[k]->end = j; edge[k]->weight = G->arc[i][j]; k++; } } } //交换i,j void swap(Edge* edge, int i, int j) { int t; t= edge[i]->begin; edge[i]->begin = edge[j]->begin; edge[j]->begin = t; t = edge[i]->end; edge[i]->end = edge[j]->end; edge[j]->end = t; t = edge[i]->weight; edge[i]->weight = edge[j]->weight; edge[j]->weight = t; } //边集数组按权值快速排序 void Quicksort(Edge* edge, int l, int r) { if (l >= r)return; int i=l-1, j=r+1, mid = edge[(l + r) / 2]->weight; while (i < j) { do i++; while (edge[i]->weight < mid); do j--; while (edge[j]->weight > mid); if (i < j) { swap(edge, i, j); } } Quicksort(edge, l, j); Quicksort(edge, j + 1, r); } //返回f的最小孩子,判断是否成环 int Find(int* parent, int f) { while (parent[f] > 0)//f的孩子存在 { f = parent[f]; } return f; } //Kruskal生成最小生成树 void MiniSpanTree_Kruskal(MGraph* G) { int i, n, m; Edge edges[MAXEDGE];//边集数组 int parent[MAXVEX];//判断是否形成环路 parent[父亲]=孩子 ChangeGtoE(G, edges);//图转为边集数组 Quicksort(edges, 0, G->numNodes);//将边集数组按权值从小到大排序 //初始化判断数组 for (i = 0; i < G->numNodes; i++)parent[i] = 0; //将各点入树 for (i = 0; i < G->numEdges; i++)//遍历每条边 { //判断是否形成环 n = Find(parent, edges[i]->begin);//找到边起始顶点的最小孩子 m = Find(parent, edges[i]->end);//找到边末尾顶点的最小孩子 if (n != m)//最小孩子不相等,则没有形成回路 { parent[n] = m;//把此结点加入到生成树中 printf("(%d,%d) %d\n", edges[i]->begin, edges[i]->end, edges[i]->weight); } } } int main() { MGraph* G; if(!(G = (MGraph*)malloc(sizeof(MGraph))))return 0; CreatMGraph(G); PrintMGraph(G); MiniSpanTree_Kruskal(G); return 0; }