最小生成树算法是给定一个无向图,及其顶点和边的权值,在确保所有顶点都是连通即整个无向图的连通分量为1的情况下使得所有边的权值之和最小的算法,这个时候其实图已经退化为树了。
下面介绍一下最小生成树的两种算法:kruskal算法和prim算法。它们都属于贪心算法,只是贪心的理解角度不同导致的两种算法。对于最小生成树,最简单的最优度量准则是:选择迄今为止已入选S中边的代价之和增量最小的边。(其中S代表已经入选最小生成树集合的边)
一)kruskal算法:
贪心准则:按边的权值非降序考察E中的边,从中选择一条代价最小的边。这种做法使得算法在构造生成树的过程中,边集S代表的子图不一定是连通的,而且为了确保最终得到一棵生成树,每选择一条边时都需要判断SUe是否包含回路。时间复杂度为0(eloge),其中e为图中边的个数,需要结合并查集解决。适合在稀疏图中。
二)prime算法:
贪心准则为:在保证S所代表的子图是一棵树的前提下选择一条最小代价边e=(u,v)。由于其选边方式已经确保S所代表的子图自然是一棵树。故无需判断边集SUe是否包含回路。
时间复杂度为O(n*n),适合在n比较小的情况下。
两种算法的实现分别如下:
prim算法的思想是加点法。即开始时任意从图中选择一个点,作为U集合,其余点为S-U集合,其中S为原图中的顶点集合,求U集合中顶点到S-U集合中顶点的最小距离,这个最小距离即为最小生成树的组成边,然后将对应最小距离的S-U集合的顶点放入U集合,然后重复执行上述操作,直至U集合=S集合。
而kruskal算法则是加边法,即将图的边先从小到大排序,然后结合并查集依次加边,注意不能形成环,这也是并查集的作用,每次成功加入的边即为最小生成树的组成边。下面是代码:
//图的邻接矩阵表示法
#include <stdio.h>
#include <stdlib.h>
#define Max 100
#define Inf 0x1111
typedef char type;
typedef struct Grap{
type data[Max];
int value[Max][Max];
int n,m;
}Grap,*pgrap;
struct Adjtrim{
int index;
int dis;
}trim[Max];
int Located(pgrap g,char ch){
for(int i=0;i<g->n;i++)
if(g->data[i]==ch)
return i;
}
void Creat_grap(pgrap g){
printf("输入图的顶点数和边数:\n");
scanf("%d%d",&g->n,&g->m);
//printf("ksgfdkj\n");
getchar();
printf