c语言之普利姆算法(prim)

来源:互联网 发布:common.js是什么文件 编辑:程序博客网 时间:2024/05/16 00:43

普利姆(Prim)算法思想

原文转载:http://www.91computer.com/datastruct/ds_tu4.asp

设:N =(V , E)是个连通网,另设U为最小生成树的顶点集,TE为最小生成树的边集。

普利姆(Prim)算法步骤:

(1)初始状态: U ={u0 },( u0 ∈V ),TE= φ,

(2)在u∈U ,v∈(V-U)所有的边(u,v)∈E中,找一条代价最小的边(u0,v0),并将边(u0,v0)并入集合TE,同时v0并入U。

(3)重复(2),直到U=V为止。

此时TE中必有n-1条边,T=(V,{TE})就是最小生成树。

注:在最小生成树的生成过程中,所选的边都是一端在U中,另一端在V-U中。选最小边的过程是一个向集合U中添加顶点的过程。

利用普利姆(Prim)算法构造一棵最小生成树举例

例:利用普利姆(Prim)算法对下面的连通网构造一棵最小生成树。

普利姆(Prim)算法

利用普利姆(Prim)算法构造最小生成树的步骤:

普利姆(Prim)算法普利姆(Prim)算法

一般情况下所添加的顶点应满足下列条件:

在生成树的构造过程中,图中 n 个顶点分属两个集合:已落在生成树上的顶点集 U 和尚未落在生成树上的顶点集V-U ,则应在所有连通U中顶点u和V-U中顶点v的边中选取权值最小的边(u’,v’),并把v’添加到U中。

Prim(普里姆)算法描述

下面我们考虑一下如何实现这个操作过程的算法。

分析 :(1)它主要有两项操作:按条件选择一条边和将顶点加入到U集合中;(2)网中的每个顶点不是在U集合中,就是在V-U集合中。为了提高算法的时间、空间效率,我们将为这个算法设计一个辅助数组closedge,用来记录从集合U到集合V-U具有最小权值的边。对每个属于V-U集合的顶点,在辅助数组中存在一个相应的分量closedge[i-1],它包括两个域,一个域用来表示在该顶点与V-U集合中某些顶点构成的边中权最小的那条边的权值,若该顶点进入U集合,则值为0;另一个域表示这条最小权值的边对应的在V-U集合中的顶点下标。其类型定义如下所示:

#define MAX_NUM  10struct {   int adjvex;      float lowcist;}closedge[MAX_NUM];

整个算法的执行过程可以描述为:

{ 初始化closedge数组的内容;  选择某个顶点k作为生成树的根结点,并将它加入到U集合中;  重复下列操作n-1次: 选择一条满足条件的边; 输出这条边的两个端点; 修改V-U集合中的顶点信息,即与U集合中构成最小权值的边。}

假设该网以邻接矩阵的形式给出,则完整的算法为:

void Mini_SpanTree(Graph G,int k,int n){//G是网的邻接矩阵,k是生成树根结点的序号,n是网的顶点数目  for (j=0;j<n;j++)   if (j!=k) closedge[j]={k,G[k][j]};  closedge[k].lowcost=0;  for (i=1;i<n;i++)  {    k=minmun(closedge);    printf(k,closedge[k].adjvex);    closedge[k].lowcost=0;     //将顶点加入U集合中    for (j=0;j<n;j++)     if (closedge[i]&&G[k][j]<closedge[j].lowcost)       closedge[j]={k,G[k][j]};  }}
////////////////////////////////////////////////////////////////////////////////////////////////////
普里姆算法:
邻接矩阵的结构定义
typedef struct
{
int no;                    //顶点编号
char info;              //存储顶点的其他信息
}VertexType;

typedef struct                                            //图的定义
{
int edges[maxsize][maxsize];                 //定义二维数组存储边的关系
int n,e;  //存储顶点数和边数
VertexType vex[maxsize];                 //存储节点信息
}MGraph;
void Prim(MGraph g, int v0, int &sum){int lowcost[maxsize],vset[maxsize];       //lowcost[]数组中存放当前生成树到剩余各定点最短边的权值,vset[i]=1表示i已经被并入生成树中int v, i, j, k, min;v = v0;for(i=1;i<=G.n;++i){lowcost[i] = g.edges[v0][i];vset[i] = 0;}vset[v] = 1;int sum = 0;                    //记录生成树的最终权值大小for(i=1;i<=G.n;++i){min = INF;                 //INF是c语言中预定义最大值常量for(j=1;j<=G.n;++j)if(vset[j] ==0 && lowcost[j] < min){min = lowcost[j];k = j;}vset[k] = 1;v = k;sum += min;for(j=1;j<=G.n;++j)                               //以刚并入的顶点V为媒介更新后选边if(vset[j] == 0 && g.edges[v][j] < lowcost[j])lowcost[j] = g.edges[v][j];} }
原创粉丝点击