【算法导论】最小生成树(prim算法)

来源:互联网 发布:中药材网络销售渠道 编辑:程序博客网 时间:2024/05/16 11:00

一,定义:

        没有权值时:一个有n个节点的联通图,生成树是,极小联通子图。包含图中所有节点,且有保持图联通的最少的边。

        边有权值时:无向联通图G=(V,E),权值函数,w:E->R。找到G的一棵最小生成树,使得 w(T)最小。w(T)为最小生成树所有边权值和。

二,prime算法

       1:初始化:U={u 0},TE={f}。 节点集U=0,边集TE=NULL,

    2:在所有u∈U, v∈V-U的边 (u,v)∈E中,找一条权最小的边(u 0,v 0),将此边加进集合TE中,并将此边的非U中顶点加入U中。
    3:如果U=V,则算法结束;否则重复步骤2。

       说明:步骤2共执行了n-1次(设n为图中顶点的数目),TE中也增加了n-1条边,这n-1条边就是需要求出的最小生成树的边。

三,源码

view plaincopy to clipboardprint?
  1. #include"stdio.h" 
  2. #include"malloc.h" 
  3. #define MaxSize 10 
  4. #define MaxNumber  999999 
  5. /*prim就是用 邻接矩阵存储的*/ 
  6. /*这里是无向图*/ 
  7. typedef struct MGraph// 
  8.     char vertex[MaxSize]; 
  9.     int arc[MaxSize][MaxSize]; 
  10.     int vertexNum,arcNum;//顶点数 边数  
  11. }MGraph,*M;  
  12.                   //顶点     顶点数  边数  
  13. void CreateMGraph(MGraph *G,char ver[],int n,int e)//创建树  
  14.     G->vertexNum=n
  15.     G->arcNum=e
  16.     int i,j; 
  17.     int ver1,ver2;   
  18.      
  19.     for(i=0;i<G->vertexNum;i++) 
  20.         { 
  21.             G->vertex[i]=ver[i];  
  22.             //printf("%5c\n",G.vertex[i]); 
  23.         }  
  24.                   
  25.     for(i=0;i<G->vertexNum;i++) 
  26.        for(j=0;j<G->vertexNum;j++) 
  27.            G->arc[i][j]=MaxNumber;//初始化数组 以后有边的 赋值 
  28.             
  29.     for(i=0;i<G->arcNum;i++) 
  30.      {/*注意输入时 不要超过数组的下标 从0开始*/ 
  31.         printf("please input the edge of two vertex\n"); 
  32.         scanf("%d%d",&ver1,&ver2); 
  33.         G->arc[ver1][ver2]=1; 
  34.         G->arc[ver2][ver1]=1; 
  35.      }   
  36.      //printf("%d\n",G.vertexNum); 
  37. void outPut(MGraph *G) 
  38. {   int i,j; 
  39.  
  40.   //printf("%d",G->vertexNum); 
  41.      
  42.     for(i=0;i<G->vertexNum;i++) 
  43.        printf("%8c",G->vertex[i]); 
  44.      
  45.     printf("\n"); 
  46.      
  47.     for(i=0;i<G->vertexNum;i++) 
  48.     { 
  49.         for(j=0;j<G->vertexNum;j++) 
  50.         { 
  51.             printf("%8d",G->arc[i][j]); 
  52.         }  
  53.         printf("\n"); 
  54.     }   
  55.      
  56. }  
  57. int MinEdge(int lowcost[],int n)//如果 不可达的边赋值为0  肯定出错 应该赋值为无穷 MaxNumber  
  58.                                 //这里要返回的是下标 而不是最小值  
  59.     int i=0
  60.     while(lowcost[i]==0) 
  61.          ++i; 
  62.     int min=lowcost[i]; 
  63.     int min_n=i; 
  64.      
  65.     for(int j=i;j<n;j++) 
  66.        if(lowcost[j]!=0&&lowcost[j]<min)  
  67.              { 
  68.                 min=lowcost[j]; 
  69.                 min_n=j
  70.             }  
  71.     //printf("sssssss%d\n",min); 
  72.     return min_n; 
  73.     //return min; 
  74. void prim(MGraph *G) 
  75.     int i,j,k; 
  76.     int lowcost[G->vertexNum];//lowcost[k]记录顶点 k 到已经加入最小生成子树 的权值 
  77.     int adjvex[G->vertexNum];  
  78.      //printf("%d\n",G->vertexNum); 
  79.     for(i=1;i<G->vertexNum;++i)//这里 i 是从 1开始  
  80.     { 
  81.         lowcost[i]=G->arc[0][i];  //初始化 U中只有 0这个顶点 让 lowcost 数组存放 0到各个顶点权值  
  82.                                   //其实  lowcost 数组 存放没有并入 U 中的点  到U 中最小权值,adjvex 则对应 该顶点  
  83.         adjvex[i]=0; //顶点 i 到 U中边中最小权值的 顶点  
  84.     } 
  85.     lowcost[0]=0; 
  86.      
  87.     for(i=1;i<G->vertexNum;++i) 
  88.     { 
  89.         k=MinEdge(lowcost,G->vertexNum);//在lowcost[]数组中寻找最短的边 
  90.         printf("<%d,%d>--$:%d\n",k,adjvex[k],lowcost[k]); //输出加入到 U 中的边  
  91.         lowcost[k]=0;  //将顶点k 加入集合U 
  92.          
  93.         for(j=1;j<G->vertexNum;++j) 
  94.         { 
  95.             if(G->arc[k][j]<lowcost[j]) 
  96.             { 
  97.                 lowcost[j]=G->arc[k][j]; 
  98.                 adjvex[j]=k; 
  99.             } 
  100.         }  
  101.           
  102.     } 
  103. /*思考过程: 0 先在U 内 lowcost 为 V-U  内点到 0 cost 
  104.              选中到 0 cost最小的 k,并通过lowcost[k]=0使得k加入 U,比较V-U 到0  跟到 k cost 取小放入 lowcost 
  105.              再选l 使得 V-U  中到 U 中最小边  ,l加入U, 让 V-U中其余点到(U-l)cost 跟 到 l cost 比较  取小的放入 lowcost 
  106.               
  107.              综上,lowcost 存放的是 V-U 的所有点 到 U的 最小权值。其中 lowcost=0表示加入U 查找最小值时,不再搜索  
  108.              求最小生成树,就是寻找分割的两部分之间的 最小权值的边。  
  109. */ 
  110. int main() 
  111.     MGraph *graph=(MGraph*)malloc(sizeof(MGraph)); 
  112.      
  113.      
  114.     char ver[4]={'a','b','c'}; 
  115.     int n=3;//顶点数 
  116.     int e=2;  
  117.      
  118.     //graph->vertexNum=n;//这个必须加上  
  119.    // printf("%d\n",graph->vertexNum); 
  120.           
  121.     CreateMGraph(graph,ver,n,e);  
  122.      
  123.    // printf("%d\n",graph->vertexNum); 
  124.      
  125.     outPut(graph); 
  126.     prim(graph); 
  127.      
  128. }