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++; //扫描下一条边
}
}
克鲁斯卡尔最短路径算法详解
最新推荐文章于 2023-10-19 13:04:42 发布