【图算法】(3)最小连通网Prim算法以及kruskal算法

来源:互联网 发布:apache服务器添加域名 编辑:程序博客网 时间:2024/06/06 09:21

1.问题的提出

如何在图中选择n-1条边,使得n个顶点间两辆可达,并且这n-1条边的权值最小?设图如下所示:

这里写图片描述

要求:
1.必须使用且仅使用该网络中的n-1条边来连接网络中的n个顶点
2.不能使用产生回路的边
3.各边上的权值总和要求最小

2.Prim算法的基本思想

1.从图N={V,E}中选择某一顶点u0进行标记,之后选择与它关联的具有最小权值的边(u0,v),并将顶点v进行标记
2.反复在一个顶点被标记,而另一个顶点未被标记的各条边中选择权值最小的边(u,v),并将未标记的顶点进行标记
3.如此进行下去,直到图中所有顶点都被标记了为止

3.算法实现步骤

1.从某一顶点u0触发,使得U={u0},TE={}
2.每次选择一条边,这条边是所有(u,v)中权值最小的边,且u∈U,v∈V-U。修改U和TE
TE = TE+{(u,v)}
U = U+{v}
3.当U≠V时,转2,否则结束

4.算法实现

#define VNUM 9              //定义点的最大数量#define MV 65535            //当两点之间不可达时,权值为65535int p[VNUM];                //临时数组int cost[VNUM];             //存储消耗int mark[VNUM];             //存储标记int matrix[VNUM][VNUM]={    { 0 , 10, MV,MV,  MV, 11, MV, MV, MV },    { 10, 0 , 18,MV,  MV, MV, 16, MV, 12 },    { MV, 18, 0, 22,  MV, MV, MV, MV, 8  },    { MV, MV, 22, 0,  20, MV, MV, 16, 21 },    { MV, MV, MV, 20, 0,  26, MV, 7,  MV },    { 11, MV, MV, MV, 26, 0,  17, MV, MV },    { MV, 16, MV, MV, MV, 17, 0,  19, MV },    { MV, MV, MV, 16, 7,  MV, 19, 0,  MV },    { MV, 12, 8, 21,  MV, MV, MV, MV, 0  },};//描述点之间的关系void prim(int sv){    int i=0;    int j=0;    if((0 <= sv)&(sv < VNUM))    {        for(i=0;i<VNUM;++i){            cost[i]=matrix[sv][i];//初始化起点权值            p[i]=sv;//记录边的信息,下标是一个顶点,值是另一个顶点            mark[i]=0;        }        mark[sv]=1;        for(i=0;i<VNUM;++i){            int min = MV;            int index = -1;            //找出最小权值的边            for(j=0;j<VNUM;++j){                if(!mark[j] && cost[j] < min){                    min = cost[j];                    index = j;                }            }            if(index > -1){                mark[index]=1;//将该顶点标记                printf("(%d,%d,%d)\n",p[index],index,cost[index]);            }            //顶点切换操作            for(j=0;j<VNUM;++j){                if(!mark[j] && (matrix[index][j] < cost[j]){                    cost[j] = matrix[index][j];                    p[j]=index;                }            }        }    }}int main(){    prim(0);    return 0;}

运行结果如下图所示
这里写图片描述

5.Kruskal算法基本思想

定义边结构体

typedef struct _tag_Edge{    int begin;    int end;    int weight;}Edge;

算法核心思想
遍历edges数组中的每个元素
通过p数组查找begin顶点的最终连接点 v1
通过p数组查找end顶点的最终链接点v2
如果v1 != v2则:
当前边为最小连通网中的边,记录链接关系p[v1];
如果v1 == v2则:
产生回路,舍弃当前边

6.比较

Prim算法是针对顶点展开的,适合于边的数量较多的情况
Kruskal算法是针对边展开的,适合于边数较少的情况

原创粉丝点击