带全最小生成树-克鲁斯卡尔算法
边的名称按照权值来排序
---变成了--->
------>
算法代码:
struct Edges
{
int begin;
int end;
};
int Find(int* parent, int f)
{
while (parent[f] > 0)
{
f = parent[f];
}
return f;
}
//Kruskal 算法生成最小生成树
void MiniSpanTree_Kurskal(MGraph G)
{
int n, m;
Edges edges[MAGEDGE]; //定义边集数组
int parent[MAXVET];//定义parent数组,用来判断边与边是否形成环路
for (int i = 0; i < G.numVertexes; i++)
{
parent[i] = 0;
}
for (int i = 0; i < G.numEdges; i++) //以边的个数,作为循环次数
{
n = Find(parent, edges[i].begin);//n=4 2 1 5 3 8 6 6 6
m = Find(parent, edges[i].end); //m=7 8 5 8 7 6 6 6 7
if (n != m) //如果n==m,则形成环路,不满足
{
parent[n] = m; //将此边的结尾顶点放入下标为起点的parent数组中,表示此顶点已经在生成树集合中
printf("(%d, %d) %d", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}
思维过程:
比如有这样的表,begin表示起点位置,end表示终点位置,weigth表示权重,按照权重的大小对edges数组排序
初始化parent数组:
1.进入i=0的for循环, edges[0].begin=4时,进入Find函数,返回f=4 ,所以n=4; edges[0].end=7时,进入Find函数,返回f=7,所以m=7;不构成环路,则parent[4]=7;
因此parent数组改变为:
此时,V4——V7便已经指过了。
2.进入i=1的for循环, edges[0].begin=2时,进入Find函数,返回f=2 ,所以n=2; edges[0].end=8时,进入Find函数,返回f=8,所以m=8;不构成环路,则parent[2]=8;
此时parent数组为:
此时,V2——V8便已经连接了
3 以此类推..... ....V0——V1便已经连接了
4.以此类推......V0——V5便已经连接了
5以此类推........V1——V8便已经连接了
6.以此类推... ....V3——V7便已经连接了
7.以此类推... ....V1——V6便已经连接了 ,
此时连接图为:
8.进入for循环,edges[0].begin=5时,进入Find函数,返回f=6 ,所以n=6; edges[0].end=6时,进入Find函数,返回f=6,所以m=6;n==m 构成环路,则舍弃V5——V6的连接;
9.进入for循环,edges[0].begin=1时,进入Find函数,返回f=6 ,所以n=6; edges[0].end=2时,进入Find函数,返回f=6,所以m=6;n==m 构成环路,则舍弃V1——V2的连接;
10.进入for循环,edges[0].begin=6时,进入Find函数,返回f=6 ,所以n=6; edges[0].end=7时,进入Find函数,返回f=7,所以m=7;
此时parent数组为:
不构成环路,V6——V7便已经连接了.
此时连接图为:,最小生成树已经构建完成!
11.V3——V4舍弃,V3——V8舍弃,V2——V3舍弃,V3——V6舍弃,V4——V5舍弃,