void InsertSort(Edge a[],int n) //这里是插入排序,就是对传入的数组进行从小到大的排序,方便克鲁斯卡尔算法的执行 { int i,j,k; Edge temp; for(i=1;i<n;i++) { temp = a[i]; //创建一个辅助变量, j=i-1; //将每一次数组的第一个值与第二个比较 while(j>=0&&temp.w<a[j].w) //大则互换,也叫插入换位 { a[j+1]=a[j]; j--; } a[j+1]=temp; } // /*for(i=0;i<n;i++) /printf("%d ",a[i].w);printf("\n");*/ //这两//句是我用来辅助你去看它的生成结果,在实际程序中可要可不要 } void Kruskal(MGraph g) //克鲁斯卡尔算法最小生成树 { int i,j,m1,m2,sn1,sn2,k; int vset[MAXV]; //辅助数组 ,用于放最小生成树节点 Edge E[MAXE]; //边集 k=0; //边数变量 //下面两个for实际上是将图的矩阵中的数据放入数组中,你去看课本上的图的矩阵,就明白了,INF是无穷大的意思, 矩阵是方矩阵,长宽各为g.n for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) if(g.edges[i][j]!=0&&g.edges[i][j]!=INF) { E[k].u=i;E[k].v=j;E[k].w=g.edges[i][j]; k++; } InsertSort(E,k); //边插入排序,就是将权值从小到大依次排列 for(i=0;i<g.n;i++) //初始化辅助数组,存储最小生成树节点的编号 vset[i]=i; //初始化为 0.1.2.3.4.5,作用后面就知道了 //vset[]这个数组是用来辅助克鲁斯卡尔算法的数组,在后面中用来判断是否会形成回路,因为一旦形成回路就不满足生成树的概念,然后你再去看最小生成树,就是 权值之和最小并且遍历了节点,并且只遍历了一次 ,此时就生成了最小生成树 k=1; //k表示当前构造最小生成树的第几条边,初值为1 j=0; //E中边的下标,初值0 while(k<g.n) //生成边数小于n时循环 { m1=E[j].u;m2=E[j].v; //取一条边的头尾顶点E[j].u和E[j].v是同步变化的 sn1=vset[m1]; sn2=vset[m2]; //分别得到两个顶点所属的集合编号 //sn1和sn2页是在同时变化,注意值,最好是将while这个过程画出来 if(sn1!=sn2) //两顶点属于不同的集合, { //该边是最小生成树的一条边 printf(" (%d,%d):%d\n",m1,m2,E[j].w); k++; //生成边数加1 for(i = 0;i<g.n;i++) //两个集合统一编号,统一为小值这里就是判断是否形成回路了,循环检查,如果有相等,直接跳过 if(vset[i]==sn2) //集合编号为sn2的改为sn1 vset[i]=sn1; } j++; //扫描下一条边 } }
克鲁斯卡尔最短路径算法详解
猜你喜欢
转载自blog.csdn.net/weixin_36708538/article/details/78634334
今日推荐
周排行