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

普利姆(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)算法构造最小生成树的步骤:

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

在生成树的构造过程中,图中 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  10
struct {
   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];
	} 
}
 
   
 
  

你可能感兴趣的:(c,Prim,算法设计)