【最小生成树】prim算法

算法分析的一般步骤:

1、文字描述:如果一个算法文字描述不清楚,就说明思路不清楚,也不可能写好。

prim算法是实现图的最小生成树。既然是图,就假设包含n个顶点,m条边。prim算法是从顶点出发的,其算法时间复杂度与顶点数目有关系。

(注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。)

算法思路:从某个顶点开始,假设v0,此时v0属于最小生成树结点中的一个元素,该集合假设u,剩下的V-v0为待判定的点,此时选取u中的顶点到V-v0中顶点的一个路径最小的边,并且将其中非u中的顶点加入到u中,循环直到u中的顶点包含图所有的顶点为止。

算法在选取最小路径的时候需要优化,具体思路:w[]数组保存各个顶点的最短路径,b[]数组保存到i顶点最短路径的顶点,比如,到0号顶点最短的路径是<v0,v3>,那么w[0]=<v0,v3>,b[0]=3;这样每次找最小路径就不是o(n*n)的代价了。

2、举例说明:

3、程序实现与说明:

复制代码
#include <stdio.h>
#include <stdlib.h>
#define count 6
void prim(int a[][count],int u[],int w[],int b[],int n)
{
    int i=0,j=0,m=0,min=100;
    for(i=0;i<count;i++)
    {
        u[i]=0;//初始化0,说明没有访问过
        w[i]=a[0][i];//初始每个顶点最短路径为到0顶点的距离
        b[i]=0;//初始每个顶点都指向0顶点
    }
    u[0]=1;//赋值1,从0顶点开始
    for(i=1;i<n;i++)
    {
        min=100;
        j=0;
        for(m=1;m<n;m++)
        {
            if(!u[m] && w[m]<min)//很关键,得到到访问顶点到未访问顶点的最短路径以及对应顶点j
            {
                min=w[m];
                j=m;
            }
        }
        u[j]=1;//把下一个顶点标为已访问
        printf("%d,%d\n",j+1,b[j]+1);//输出结果
        for(m=1;m<n;m++)
        {
            if(!u[m] && a[j][m]<w[m])//此时,u集合里面多了一个顶点j,要重新更新最短路径以及对应的顶点
            {
                w[m]=a[j][m];
                b[m]=j;
            }
        }
    }
}
int main()
{
    int u[count],w[count],b[count],a[count][count];
    int i=0,j=0;
    for(i=0;i<count;i++)
    {
        for(j=0;j<count;j++)
        {
                a[i][j]= 100;
        }
    }
    a[0][1]=6,a[0][2]=1,a[0][3]=5;
    a[1][0]=6,a[1][2]=5,a[1][4]=3;
    a[2][0]=1,a[2][1]=5,a[2][3]=5,a[2][4]=6,a[2][5]=4;
    a[3][0]=5,a[3][2]=5,a[3][5]=2;
    a[4][1]=3,a[4][2]=6,a[4][5]=6;
    a[5][3]=2,a[5][2]=4,a[5][4]=6;
    prim(a,u,w,b,count);
    return 0;
}
复制代码

4、时间复杂度:o(n*n)

参考博客:https://www.cnblogs.com/nannanITeye/p/3446424.html

posted @ 2018-11-29 22:55  听风不成泣  阅读(1542)  评论(0编辑  收藏  举报