最小生成树prim算法

来源:互联网 发布:三星智能电视直播软件 编辑:程序博客网 时间:2024/06/08 11:37

       普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。


借用维基百科的定义就是:


       从单一顶点开始,普里姆算法按照以下步骤逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点。


       输入:一个加权连通图,其中顶点集合为V,边集合为E;


       初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {};


       重复下列操作,直到Vnew = V:


       在集合E中选取权值最小的边(u, v),其中u为集合Vnew中的元素,而v则是V中没有加入Vnew的顶点(如果存在有多满足前述条件即具有相同权值的边,则可任意选取其中之一);


       将v加入集合Vnew中,将(u, v)加入集合Enew中;


       输出:使用集合Vnew和Enew来描述所得到的最小生成树。



       其实算法的基本思想就是一个贪心的概念,选取一个结点当做源结点进行扩展,扩展方法就是选取源结点与其他结点之间权值最小的那个结点,因为如果构造一个最小生成树一定会包含源节点,包含源节点那么就一定会选取距离源结点最近的那条边包含进来.之后选取一个结点之后就构成了一个最小生成树集合,将所有结点分成了两部分,每次循环依次最小生成树集合都会增加一个结点,所以只需循环verNum-1次就可以得到最终结果.


       其中要不断维护的就是一个最小边的数组lowcost,也就是从集合出发到其他结点的最小边长,以便筛选结点时使用,已经选进集合的结点i的lowcost[i]将被赋值为0.每次循环中选取min的过程其实可以使用优先队列来实现,自动排序,每次只需出队就可以了.


typedef struct {    int arc[MAXVEX][MAXVEX];    int numVertexes;}MGraph;void prim(MGraph G){int i,j;//循环变量int min;//存放每次循环得出的边最小值int k;//记录下一次要扩展的结点int adjvex[MAXVEX];//存放全职最小的边的另一个结点,如adjvex[2] = 4;连接最小值边的为结点2到结点4.int lowcost[MAXVEX];//存放最小生成树集合中结点到每个结点的最小权值.lowcost[0] = 0;//将最小权值赋值为0说明该结点已经在最小生成树集合中adjvex[0] = 0;//结点0到结点0的权值最小,所以adjvex[0] = 0.for (i = 0; i < G.numVertexes; i++)//初始化,结点0所有的边值赋值给最小全集数组{lowcost[i] = G.arc[0][i];adjvex[i] = 0;}for (i = 1; i < G.numVertexes; i++)//从1结点开始循环遍历,每循环依次往最小生成树集合中增加一个结点{min = INFINITY;j = 1;k = 0;while(j < G.numVertexes)//循环查找集合向外扩展最小的边{if (lowcost[j]!=0&&lowcost[j]<min)//lowcost=0代表结点已经在集合中{min = lowcost[j];//记录最小边的值k = j;//记录下一个要扩展的结点}j++;}cout << "(" << adjvex[k] << ", " << k << ")" << "  "; // 打印当前顶点边中权值最小的边        lowcost[k] = 0;// 将当前顶点的权值设置为0,表示此顶点已经完成任务for(j = 1; j < G.numVertexes; j++)//扩展集合中的边,更新lowcost数组.{if(lowcost[j]!=0&&G.arc[k][j] < lowcost[j]){lowcost[j] = G.arc[k][j];adjvex[j] = k;}}}}



0 0