最小生成树之克鲁斯卡尔算法
版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/RowandJJ/article/details/37602723
克鲁斯卡尔算法:
如果连通网N = {V,{E}},则令最小生成树的初始状态为仅仅有n个顶点而无边的非连通图T = {V,{}}。图中每一个顶点自成一个连通分量。
在E中选择一个最小代价边。若该边依附的顶点落在T中的不同连通分量上,则将此边增加到T中。否则舍去此边而选择下一条最小代价边【最小生成树不存在环】。
依次类推,直至T中全部顶点都在同一连通分量上为止。
【连通分量:无向图的极大连通子图】
考虑例如以下连通图:
用边集数组表示为:
注:这里为了算法方便。将边集数组内容按权值从小到大进行了排序。
以下使用克鲁斯卡尔算法构造最小生成树(对比代码):
1.初始化辅助数组(parent):
2.从已经排好序的边集数组中取出第一行数据,分别计算Find(begin)和Find(end),看是否会形成环(m==n)。若不形成环。则输出,并更新辅助数组(parent[n] = m),在这里。find(0) = 0,find(2) = 2
所以将0---2这条边纳入生成树集合:
辅助数组为:
3.第二次循环,会将3---5纳入生成树集合:
辅助数组为:
4.如此再循环两次:
辅助数组:
此时,再准备下次循环时,相应的是边集数组的第四组:
计算find(0)=5,find(3)=5,即m==n,形成了环。所以被舍去!直到遇到边集数组第六组时才不会形成环。
终于生成树为:
实现:
/*******************************************
最小生成树之克鲁斯卡尔算法
by Rowandjj
2014/7/9
*******************************************/
#include<iostream>
using namespace std;
#define MAX_VERTEX_NUM 20//最大顶点数
typedef struct _EDGE_
{
int begin;//起始点序号
int end;//终点序号
int weight;//权值
}Edge[MAX_VERTEX_NUM];//边集数组
typedef struct _GRAPH_
{
Edge edge;//边集数组
int numVertiexs;//顶点数
int numEdges;//边数
}Graph;//图存储结构--->边集数组结构
//------------------------------------------
void CreateGraph(Graph* g);//构建有权无向图g
void Display(Graph g);//输出图g的相关信息
int Find(int *parent,int f);
void MiniSpanTree_Kruskal(Graph g);//最小生成树之克鲁斯卡尔算法
//------------------------------------------
void CreateGraph(Graph* g)
{
int i;
cout<<"输入顶点数、边数:";
cin>>g->numVertiexs;
cin>>g->numEdges;
cout<<"按权值从小到大顺序输入每条边的两个顶点及权值:"<<endl;
//初始化边集数组
for(i = 0; i < g->numEdges; i++)
{
cin>>g->edge[i].begin;
cin>>g->edge[i].end;
cin>>g->edge[i].weight;
}
}
void Display(Graph g)
{
cout<<"顶点数:"<<g.numVertiexs<<" 边数:"<<g.numEdges<<endl;
cout<<"打印各边信息:"<<endl;
for(int i = 0; i < g.numEdges; i++)
{
cout<<g.edge[i].begin<<"---->"<<g.edge[i].end<<" : "<<g.edge[i].weight<<endl;
}
}
int Find(int *parent,int f)
{
while(parent[f] > 0)
{
f = parent[f];
}
return f;
}
void MiniSpanTree_Kruskal(Graph g)//最小生成树之克鲁斯卡尔算法
{
int i;
int m,n;
int parent[MAX_VERTEX_NUM];//定义辅助数组,用来推断边与边之间是否存在环路
//1.初始化辅助数组
for(i = 0; i < g.numVertiexs; i++)
{
parent[i] = 0;
}
//2.计算最小生成树
for(i = 0; i < g.numEdges; i++)
{
n = Find(parent,g.edge[i].begin);
m = Find(parent,g.edge[i].end);
if(n != m)//如果没有形成c环,那么输出
{
parent[n] = m;//表示此顶点已经在生成树集合中
cout<<g.edge[i].begin<<"--->"<<g.edge[i].end<<" : "<<g.edge[i].weight<<endl;
}
}
}
//------------------------------------------
int main()
{
Graph g;
CreateGraph(&g);
Display(g);
cout<<"\n最小生成树例如以下\n"<<endl;
MiniSpanTree_Kruskal(g);
return 0;
}
測试:
posted on 2019-04-19 14:47 xfgnongmin 阅读(398) 评论(0) 编辑 收藏 举报