最小生成树-普利姆算法

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

普利姆(Prim)算法

普利姆(Prim)算法思想

设: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]};
  }
}

你可能感兴趣的:(最小生成树-普利姆算法)