(1)Prim
算法如下,头文件:
#define INFINITY10000 #define MAX_VERTEX_NUM20 typedefint InfoType; typedef char VertexType; typedef int VRType; typedef enum ... {DG,DN,UDG,UDN} GraphKind; typedef struct ArcCell ... { VRTypeadj; InfoType * info; } ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct ... { VertexTypevexs[MAX_VERTEX_NUM]; AdjMatrixarcs; int vexnum,arcnum; GraphKindkind; } MGraph; int weight[][ 6 ] = ... { ... { 0 , 6 , 1 , 5 ,INFINITY,INFINITY} , ... { 6 , 0 , 5 ,INFINITY, 3 ,INFINITY} , ... { 1 , 5 , 0 , 5 , 6 , 4 } , ... { 5 ,INFINITY, 5 , 0 ,INFINITY, 2 } , ... {INFINITY, 3 , 6 ,INFINITY, 0 , 6 } , ... {INFINITY,INFINITY, 4 , 2 , 6 , 0 } }; // #defineINPUT1 typedefstruct ... { int parent; int cost; } mst_prim_closedge;
源文件:
#include " graph.h " #include" stdio.h " #include" stdlib.h " void createDG(MGraph & g) ... {} void createDN(MGraph & g) ... {} void createUDG(MGraph & g) ... {} int locate(MGraphg, char name) ... { for ( int i = 0 ;i < g.vexnum;i ++ ) ... { if (name == g.vexs[i]) ... { return i; } }return - 1 ; } void createUDN(MGraph & g) ... { #ifdefINPUT printf( " inputthenumberofvertexandarcs: " ); scanf( " %d%d " , & g.vexnum, & g.arcnum); fflush(stdin); #else printf(" inputthenumberofvertex: " ); scanf( " %d " , & g.vexnum); fflush(stdin); #endif int i = 0 ,j = 0 ,k = 0 ; printf( " inputthenameofvertex: " ); for (i = 0 ;i < g.vexnum;i ++ ) ... { scanf( " %c " , & g.vexs[i]); fflush(stdin); } for (i = 0 ;i < g.vexnum;i ++ ) ... { for (j = 0 ;j < g.vexnum;j ++ ) ... { g.arcs[i][j].adj = INFINITY; g.arcs[i][j].info = NULL; } } #ifdefINPUTchar v1,v2; int w; printf( " inputthe%darcsv1v2andweight: " ,g.arcnum); for (k = 0 ;k < g.arcnum;k ++ ) ... { scanf( " %c%c%d " , & v1, & v2, & w); fflush(stdin); i = locate(g,v1); j = locate(g,v2); g.arcs[i][j].adj = w; } #else printf(" nowconstructingthematrixofgraph... " ); for (i = 0 ;i < g.vexnum;i ++ ) ... { for (j = 0 ;j < g.vexnum;j ++ ) ... { g.arcs[i][j].adj = weight[i][j]; } }#endif }void printGraph(MGraphg) ... { for ( int i = 0 ;i < g.vexnum;i ++ ) ... { for ( int j = 0 ;j < g.vexnum;j ++ ) ... { printf( " %d " ,g.arcs[i][j].adj); } printf(" " ); } }void createGragh(MGraph & g) ... { printf( " pleaseinputthetypeofgraph: " ); scanf( " %d " , & g.kind); switch (g.kind) ... { case DG: createDG(g); break ; case DN: createDN(g); break ; case UDG: createUDG(g); break ; case UDN: createUDN(g); printGraph(g); break ; } }// getthemincostvertice,returntheindex int minimum(mst_prim_closedge * closedge, int n) ... { int ret = - 1 ; int retcost = INFINITY; for ( int i = 0 ;i < n;i ++ ) ... { if (closedge[i].cost > 0 && closedge[i].cost < retcost) ... { ret = i; retcost = closedge[i].cost; } }return ret; } /**/ /* * *theprimalgorithmofmst(minimumcostspanningtree) *MGraphg:thegraph *charstart:thestartpoint */ void mst_prim(MGraphg, char start) ... { mst_prim_closedge * closedge = (mst_prim_closedge* )malloc( sizeof (mst_prim_closedge) * g.vexnum); // gettheindexofstart int index = locate(g,start); // inittheclosestedgearray int i = 0 ; for (;i < g.vexnum;i ++ ) ... { closedge[i].parent = index; closedge[i].cost = g.arcs[index][i].adj; } // choosethenextn-1vertex printf( " nowthemstis: " ); int j = 0 ; for (i = 1 ;i < g.vexnum;i ++ ) ... { j = minimum(closedge,g.vexnum); printf( " %c,%c,%d " , g.vexs[closedge[j].parent],g.vexs[j],closedge[j].cost); // jjointheU closedge[j].cost = 0 ; // updatetheclosedge for ( int k = 0 ;k < g.vexnum;k ++ ) ... { if (g.arcs[j][k].adj > 0 && g.arcs[j][k].adj< closedge[k].cost) ... { closedge[k].cost = g.arcs[j][k].adj; closedge[k].parent = j; } } } }void main() ... { MGraphg; createGragh(g); char start; printf( " inputthestartpointofmst: " ); scanf( " %c " , & start); mst_prim(g,start); }
程序的执行结果为:
pleaseinputthetypeofgraph: 3 inputthenumberofvertex:6 inputthenameofvertex: a b c d e fnow constructingthematrixofgraph... 0 6 1 5 10000 10000 6 0 5 10000 3 10000 1 5 0 5 6 4 5 10000 5 0 10000 2 10000 3 6 10000 0 6 10000 10000 4 2 6 0 inputthestartpointofmst: anow themst is : a,c, 1 c,f,4 f,d,2 c,b,5 b,e,3 Pressanykeyto continue
算法的复杂度:从函数mst_prim()可知,时间复杂度为O(n*n),适用于求边稠密的network的mst。
(2)Kruskal
时间复杂度为O(e*log(e)),适用于求边稀疏的network的mst。
算法思想:“等价类,并查集,边排序,选小边”。
代码如下,头文件添加:
typedef struct ... { int v1; int v2; int cost; int used; } mst_kruskal_edge;
源文件添加:
// gettheclassofi int findparent( int * parent, int i) ... { while (parent[i] != - 1 ) ... { i = parent[i]; } return i; } // getthesmallestedgethathasnotused int getMin(mst_kruskal_edge * edge, int num) ... { int cost = INFINITY,index = - 1 ; for ( int i = 0 ;i < num;i ++ ) ... { if (edge[i].used == 0 && edge[i].cost < cost) ... { cost = edge[i].cost; index = i; } }return index; } /**/ /* * *thekruskalofmst */ void mst_kruskal(MGraphg) ... { // firstconstructtheedgearray mst_kruskal_edge * edge = (mst_kruskal_edge * ) malloc( sizeof (mst_kruskal_edge) * g.vexnum / 2 * (g.vexnum - 1 )); int i,j,k = 0 ; for (i = 0 ;i < g.vexnum;i ++ ) ... { for (j = i + 1 ;j < g.vexnum;j ++ ) ... { if (g.arcs[i][j].adj > 0 && g.arcs[i][j].adj != INFINITY) ... { edge[k].v1 = i; edge[k].v2 = j; edge[k].cost = g.arcs[i][j].adj; // thisedgeisnotused edge[k].used = 0 ; k ++ ; } } } printf(" thenumofedgeis:%d " ,k); // theparentarray,representtheclassofthevertice int * parent = ( int * )malloc( sizeof ( int ) * g.vexnum); // inititwith-1 for (i = 0 ;i < g.vexnum;i ++ ) ... { parent[i] = - 1 ; } // constructthemst printf( " nowconstructingthemst... " ); for (i = 0 ;i < k;i ++ ) ... { int index = getMin(edge,k); if (index != - 1 ) ... { int p1 = findparent(parent,edge[index].v1); int p2 = findparent(parent,edge[index].v2); if (p1 != p2) ... { printf( " %c,%c,%d " , g.vexs[edge[index].v1],g.vexs[edge[index].v2],edge[index].cost); parent[p2] = p1; } edge[index].used= 1 ; } else ... { break ; } } }void main() ... { MGraphg; createGragh(g); /**/ /* charstart; printf("inputthestartpointofmst: "); scanf("%c",&start); mst_prim(g,start);*/ mst_kruskal(g); }
程序的执行结果为:
pleaseinputthetypeofgraph: 3 inputthenumberofvertex:6 inputthenameofvertex: a b c d e f nowconstructingthematrixofgraph...0 6 1 5 10000 10000 6 0 5 10000 3 10000 1 5 0 5 6 4 5 10000 5 0 10000 2 10000 3 6 10000 0 6 10000 10000 4 2 6 0 thenumofedgeis : 10 nowconstructingthemst... a,c,1 d,f,2 b,e,3 c,f,4 b,c,5 Pressanykeytocontinue
说明:kruskal至多对e条边各扫描一次,上面的查找算法的复杂度是O(e),所以实现的kruskal的复杂度是O(e*e)。但是如果使用堆排序,每次的查找复杂度可以变成O(log(e))(第一次需要O(e)来建立堆),从而Kruskal的复杂度是O(e * log(e))。