详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

2020-01-06 13:45:16王旭

(3)结束。
当无向网采用二维数组存储的邻接矩阵存储时,Prim 算法的C 语言实现为:

  1. //记录从顶点集U到V—U的代价最小的边的辅助数组定义:    // struct{  
  2.  // VertexType adjvex;    // VRType lowcost;  
  3.  // }closedge[ MAX_VERTEX_NUM ]   void MiniSpanTree_PRIM (MGraph G,VertexType u){  
  4. //用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。    k =LocateVex(G,u);  
  5.  for(j=0; j<G.vexnum; ++j)     if(j!=k) closedge[j] ={u ,G.arcs[k][j].adj}; // {adjvex , lowcost}  
  6.  closedge[k].lowcost =0; //初始,U={u}    for( i=1;i<G.vexnum;++i){ //选择其余G.vexnum-1个顶点  
  7.   k=minimum(closedge);     printf(closedge[k].adjvex, G.vexs[k]);//输出生成树的边  
  8.   //第k顶点并入U集     closedge[k].lowcost=0;  
  9.   for(j=0; j<G.vexnum; ++j)      if (G.acrs[k][j].adj<closedge[j].lowcost) closedge[j]={G.vexs[k],G.arcs[k][j].adj};  
  10.  }//for   }//MiniSpanTree  
?

假设网中有n个顶点,则第一个进行初始化的循环语句的频度为n,第二个循环语句的频度为n-1。其中有两个内循环:其一是在closedge[v].lowcost中求最小值,其频度为n-1;其二是重新选择具有最小代价的边,其频度为n。 由此,普里姆算法的时间复杂度为O(n2),与网中的边数无关,因此适用于求边稠密的网的最小生成树。
2.克鲁斯卡尔(Kruskal) :由点到线,适合边稀疏的网。时间复杂度:O(e * loge)

Kruskal 算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。

基本思想是:

1) 设无向连通网为G=(V,E),令G 的最小生成树为T,其初态为T=(V,{}),即开始时,最小生成树T 由图G 中的n 个顶点构成,顶点之间没有一条边,这样T 中各顶点各自构成一个连通分量。

2) 在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量,则将此边加入到T中,否则舍弃此边而选择下一条边(若该边依附的两个顶点属于同一个连通分量,则舍去此边,以免造成回路)。依此类推,当T 中的连通分量个数为1 时,此连通分量便为G 的一棵最小生成树。