【最小生成树】kruskal算法C语言实现
程序员文章站
2024-02-27 23:08:15
...
系列文章:【最小生成树】Prim算法C语言实现
kruskal(克鲁斯卡尔)算法
时间复杂度:O(NlogN)(N为边数)
kruskal算法又称“加边法”,用于边数较少的稀疏图
方法:每次找图中权值最小的边(此算法中对于权值的排序运用了快速排序的方法),将边连接的两个顶点加入最小生成树集合中
注意:相同权值任选其中一个即可,但是不允许出现闭合回路的情况(此处运用了并查集的思想)。
这里推荐一个B站的动画介绍的两种最小生成树的原理,建议先看完动画再看代码:
注:动画大概8min
最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示
C语言代码实现
#include <stdio.h>
#define MAXE 100
#define MAXV 100
typedef struct{
int vex1; //边的起始顶点
int vex2; //边的终止顶点
int weight; //边的权值
}Edge;
void kruskal(Edge E[],int n,int e)
{
int i,j,m1,m2,sn1,sn2,k,sum=0;
int vset[n+1];
for(i=1;i<=n;i++) //初始化辅助数组
vset[i]=i;
k=1;//表示当前构造最小生成树的第k条边,初值为1
j=0;//E中边的下标,初值为0
while(k<e)//生成的边数小于e时继续循环
{
m1=E[j].vex1;
m2=E[j].vex2;//取一条边的两个邻接点
sn1=vset[m1];
sn2=vset[m2];
//分别得到两个顶点所属的集合编号
if(sn1!=sn2)//两顶点分属于不同的集合,该边是最小生成树的一条边
{//防止出现闭合回路
printf("V%d-V%d=%d\n",m1,m2,E[j].weight);
sum+=E[j].weight;
k++; //生成边数增加
if(k>=n)//没有边或者找到的边>顶点数减1都退出循环
break;
for(i=1;i<=n;i++) //两个集合统一编号
if (vset[i]==sn2) //集合编号为sn2的改为sn1
vset[i]=sn1;
}
j++; //无论上一条边是否被收入最下生成树,都要扫描下一条边
//k++与j++的位置不同,k++在循环内部(只有满足条件才能被收入最小生成树),j++在循环外部
}
printf("the lowest weight=%d\n",sum);
}
void swap(Edge arr[],int low,int high)
{
Edge temp;
temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
int fun(Edge arr[],int low,int high)
{
int key;
Edge lowx;
lowx=arr[low];
key=arr[low].weight;
while(low<high)
{
while(low<high && arr[high].weight>=key)
high--;
if(low<high)
swap(arr,low,high);
//arr[low++]=arr[high];
while(low<high && arr[low].weight<=key)
low++;
if(low<high)
swap(arr,low,high);
//arr[high--]=arr[low];
}
arr[low]=lowx;
return low;
}
void quick_sort(Edge arr[],int start,int end)
{
int pos;
if(start<end)
{
pos=fun(arr,start,end);
quick_sort(arr,start,pos-1);
quick_sort(arr,pos+1,end);
}
}
void gen(Edge E[],int vertex,int edge)
{
for(int i=0;i<edge;i++)
scanf("%d%d%d",&E[i].vex1,&E[i].vex2,&E[i].weight);
}
int main()
{
Edge E[MAXE];
int vertex,edge;
//freopen("1.txt","r",stdin);//文件输入
printf("please intput the vertexs and edges:\n");
scanf("%d%d",&vertex,&edge);
gen(E,vertex,edge);
quick_sort(E,0,edge-1);
kruskal(E,vertex,edge);
}
输入:
6 9
1 4 5
3 4 5
1 3 1
4 6 2
2 5 3
2 3 5
3 5 6
1 2 6
3 6 4
输出:
V1-V3=1
V4-V6=2
V2-V5=3
V3-V6=4
V2-V3=5
the lowest weight=15
上一篇: R语言实现具体的粒子群优化算法
下一篇: 例说java常用日志管理