最小生成树:

n个顶点,用n-1条边把一个连通图连接起来,并且使得权值和最小。

  1. /* 
  2. *1.初始化两个数组,一个用于存放边权值,一个用来存放边权值的起始点 
  3. *2.赋初值,从0开始,所有边权值都是和v0相关,所有边权值的起始点都是v0  
  4. *3.大循环1到MG.numVertexes-1次  
  5. *4.遍历边权值数组,找当前数组中的最小值,并将终点保存在k中  
  6. *5.打印边  
  7. *6.将加入的顶点的lowcost设置为0  
  8. *7.使用新加入的顶点的邻接矩阵来更新lowcost数组和adjvex数组  
  9. * 
  10. * 
  11. */  
  12. void MiniSpanTree_Prim(MGraph MG){ 
  13.     int min,i,j,k; 
  14.     int adjvex[MAXVEX];//存储与边对应的相关起始顶点  
  15.     int lowcost[MAXVEX];//存储顶点间边的权值 
  16.     lowcost[0] = 0;//权值为0表示此小标(V0)的顶点已经加入到了生成树中  
  17.     adjvex[0] = 0; //初始化第一个顶点的下标为0 
  18.     for(i=1;i<MG.numVertexes;i++){ 
  19.         lowcost[i] = MG.arc[0][i];//将v0顶点相关的边的权值存储数组中 
  20.         adjvex[i] = 0;//这些边的起点都是v0,所以下标都是0 
  21.     } 
  22.     for(i=1;i<MG.numVertexes;i++){ 
  23.         min = INFINITY;//最小权值初始化为无穷,通常将infinity设置为不可能的大数字 
  24.         j=1;k=0; 
  25.         while(j<MG.numVertexes){//在lowcost数组中寻找最小值,并记下最小值的终点存储在k中  
  26.             if(lowcost[j]!=0 && lowcost[j]<min){ 
  27.                 min = lowcost[j]; 
  28.                 k = j; 
  29.             } 
  30.             j++; 
  31.         } 
  32.         printf("(%d,%d)",adjvex[k],k);//打印边,起点和终点 
  33.         lowcost[k] = 0;//将当前顶点的权值设置为0,表示此顶点已经完成任务了 
  34.         for(j=1;j<MG.numVertexes;j++){//更新lowcost数组,使用刚添加进最小生成树的那个结点的行!  
  35.             if(lowcost[j]!=0 && MG.arc[k][j]<lowcost[j]){//如果下标为k的顶点各个边权值小于lowcost的边权值  
  36.                 lowcost[j] = G.arc[k][j];//更新lowcost数组  
  37.                 adjvex[j] = k;//更新与边权值相关联的边起点信息  
  38.             } 
  39.         }  
  40.     } 
  41. }  
  42. /* 
  43. *1.定义一个边集,一个结点集,将结点集全部初始化为0,边集按照权的大小排列  
  44. *2.循环边集中的每一条边,检查每条边的起点和终点,如果相同就继续循环,否则打印并修改parent  
  45. *3.定义一个方法Find来寻找结点的走向  
  46. * 
  47. * 
  48. * 
  49. */  
  50. typedef struct
  51.     int begin; 
  52.     int end; 
  53.     int weight; 
  54. }Edge; 
  55. void MiniSpanTree_Kruskal(MGraph MG,Edge edges[]){//此处使用元素类型为Edge的边集数组,已经按照权值由小到大排列  
  56.     int i,n,m; 
  57.     int parent[MAXVEX];//定义一数组用来判断边与边是否形成回路 
  58.      
  59.     for(i=0;i<MG.numVertexes;i++){//初始化数组为0  
  60.         parent[i] = 0; 
  61.     } 
  62.     for(i=0;i<MG.numEdges;i++){//循环每一条边  
  63.         n = Find(parent,edges[i].begin);// 
  64.         m = Find(parent,edges[i].end);// 
  65.         if(n != m){//如果m、n不等说明此边没有与现有的生成树形成环路  
  66.             parent[n] = m;//数组下标记录了边起点,数组值记录了边终点  
  67.             printf("(%d,%d)%d",edges[i].begin,edges[i].end,edges[i].weight); 
  68.         } 
  69.     } 
  70.  
  71. int Find(int *parent,int f){//查找从f这个坐标开始能走到的最远的结点是哪里  
  72.     while(parent[f]>0){//如果最后走到的最远的结点相同,说明是又环路生成的  
  73.         f = parent[f]; 
  74.     } 
  75.     return f;