克鲁斯卡尔最短路径算法详解

									              			


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
今日推荐