利用Krusal算法求一个图的最小生成树,设计Kruskal算法求解邻接矩阵存储结构最小生成树的函数。
首先Kruskal算法是以边为目的构建的,要构建最小生成树,我们可以分成以下几步。
1.将邻接矩阵先化为顶点,顶点,权值的数组。
2.将权值的大小按从小到大的顺序排列。
3.依次将权值从小到大的边放入个顶点之间。
4.如果放入权值的边形成了环就将其抛出。
5.当放入边数等于顶点数减一时,成功。
实现函数
Kruskal.h
#include "SeqList.h"
#include "AdjMGraph.h"
#include "AdjMGraphCreate.h"
void Swapn(RowColWeight* a, int i, int j)
{
int temp;
temp = a[i].row;
a[i].row = a[j].row;
a[j].row = temp;
temp = a[i].col;
a[i].col = a[j].col;
a[j].col = temp;
temp = a[i].weight;
a[i].weight = a[j].weight;
a[j].weight = temp;
}
void MinSpanTree_Kruskal(AdjMWGraph G, RowColWeight a[])
{
int i, j = 0, temp, k = 0, n, m, num = 0;
int parent[MaxSize]; //用来判断边与边是否会成环
for (i = 0; i < G.Vertices.size - 1; i++)
{
for (j = i + 1; j < G.Vertices.size; j++)
{
if (G.edge[i][j] < MaxWeight)
{
a[k].row = i;
a[k].col = j;
a[k].weight = G.edge[i][j];
k++;
}
}
}
for (i = 0; i < G.numOfEdges; i++)
{
for (j = i + 1; j < G.numOfEdges; j++)
{
if (a[i].weight > a[j].weight)
{
Swapn(a, i, j);
}
}
}
printf("权值排序之后的为:\n");
for (i = 0; i < G.numOfEdges; i++)
{
printf("(%c, %c)= %d\n", a[i].row + 97, a[i].col + 97, a[i].weight);
}
for (i = 0; i < G.Vertices.size; i++)
{
parent[i] = 0; //初始化数组值为 0
}
//循环每一条边
for (i = 0; i < G.numOfEdges; i++)
{
n = Find(parent, a[i].row);
m = Find(parent, a[i].col);
if (n != m) //n!=m,说明没有成环,加入生成树
{
//将此边的结尾顶点放入下标为起点的parent中(n是起始顶点,m是结尾顶点)
//n---m 这条边符合条件
//表示该顶点已经在生成树集合中
parent[n] = m;
printf("Kruskal最小生成树步骤为:\n");
printf("第%d步(%c,%c),weight = %d\n", ++num, a[i].row + 97, a[i].col + 97, a[i].weight);
}
}
}
//查找连线顶点的尾部下标
int Find(int* parent, int f)
{
while (parent[f] > 0)
{
f = parent[f];
}
return f;
}
测试主函数
#include <stdio.h>
#include <stdlib.h>
typedef char DataType;
#define MaxSize 10
#define MaxVertices 10
#define MaxWeight 999
#include "SeqList.h"
#include "Kruskal.h"
#include "AdjMGraph.h"
#include "AdjMGraphCreate.h"
int main(void)
{
AdjMWGraph g1;
DataType a[] = { 'a','b','c','d','e' };
RowColWeight rcw[] = { {0,1,3},{0,4,1},
{1,2,5},{1,4,4},{2,4,6},{2,3,2},
{3,4,7 } };
int n = 5, e = 7;
int i, j,z;
CreatGraph(&g1, a, n, rcw, e);
printf("顶点的集合为:");
for (i = 0; i < g1.Vertices.size; i++)
printf("%c ", g1.Vertices.list[i]);
printf("\n");
for (i = 0; i < g1.Vertices.size; i++)
{
for (j = 0; j < g1.Vertices.size; j++)
{
g1.edge[j][i] = g1.edge[i][j];//实现无向图邻接矩阵的对称性
}
}
printf("权值集合为:\n");
for (i = 0; i < g1.Vertices.size; i++)
{
for (j = 0; j < g1.Vertices.size; j++)
printf("%5d", g1.edge[i][j]);
printf("\n");
}
MinSpanTree_Kruskal(g1,rcw);
return 0;
}