本文主要是介绍克鲁斯卡尔算法(Kruskal),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
克鲁斯卡尔(Kruskal)算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。假设 G=(V,E) 是一个具有 n 个顶点的带权连通图,
1) 设置
2) 将图
实现克鲁斯卡尔算法的关键是,如何判断选取的边是否与生成树中已保留的边形成回路,这可以通过判断边的两个顶点所在的连通分量的方法来解决。
为此设置一个辅助数组 vset[0..n−1] , 它用于判定两个顶点之间是否连通。数组元素 vset[i] (初值为 i )代表序号为
采用 E 数组存放图
typedef struct
{ int u; //边的起始顶点int v; //边的终止顶点int w; //边的权值
} Edge;
Kruskal算法如下:
void SortEdge(MGraph g,Edge E[]) //从邻接矩阵产生权值递增的边集
{int i,j,k=0;Edge temp;for (i=0;i<g.vexnum;i++)for (j=0;j<g.vexnum;j++)if (g.edges[i][j]<INF){E[k].u=i;E[k].v=j;E[k].w=g.edges[i][j];k++;}for (i=1;i<k;i++) //按权值递增有序进行直接插入排序 {temp=E[i];j=i-1; //从右向左在有序区E[0..i-1]中找E[i]的插入位置while (j>=0 && temp.w<E[j].w) { E[j+1]=E[j]; //将权值大于E[i].w的记录后移j--;}E[j+1]=temp; //在j+1处插入E[i]}
}
void Kruskal(Edge E[],int n,int e)
{int i,j,m1,m2,sn1,sn2,k;int vset[MAXE];for (i=0;i<n;i++) vset[i]=i; //初始化辅助数组k=1; //k表示当前构造最小生成树的第几条边,初值为1j=0; //E中边的下标,初值为0while (k<n) //生成的边数小于n时循环{ m1=E[j].u;m2=E[j].v; //取一条边的头尾顶点sn1=vset[m1];sn2=vset[m2]; //分别得到两个顶点所属的集合编号if (sn1!=sn2) //两顶点属于不同的集合,该边是最小生成树的一条边{ printf(" (%d,%d):%d\n",m1,m2,E[j].w);k++; //生成边数增1for (i=0;i<n;i++) //两个集合统一编号if (vset[i]==sn2) //集合编号为sn2的改为sn1vset[i]=sn1;}j++; //扫描下一条边}
}
克鲁斯卡尔算法的时间复杂度为
这篇关于克鲁斯卡尔算法(Kruskal)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!