一个图的生成树为,该生成树的点集合V等于图的点集合V,树的边E‘是图边集合E的子集,最小生成树是这些边集合的所有边的权值之和最小。
这里介绍一种求最小生成树的算法,即prim算法;这是一个贪心算法,这个算法的思想是从一个点开始,找到所有的边,将这个点到所有点的开销,也就是边的权值;利用一个数组存储所有的开销,在查找的过程中更新开销;然后每次遍历点集合,将哪些没有加入最小生成树且权重最小的点加入最小生成树;重复以上操作,直到所有的点都加入最小生成树集合。
下面是最要的算法实现:
vector<int> prim(graph *g,int start)
{
bool intree[MAX+1];//用于判断节点是否在最小生成树中间
edgenode *p;//临时存放节点
int distance[MAX+1];//找出下一个权值最小的边
int w;//下一个候选的点
vector<int> trees;
memset(intree,false,(MAX+1)*sizeof(bool));
memset(parent,-1,sizeof(parent));
for(int i=0;i<MAX+1;i++)
{
distance[i]=INT_MAX;
}
w=start;
while(!intree[w])
{
intree[w]=true;
p=g->nodes[w];
trees.push_back(w);
while(p)
{
int y=p->y;
if((p->weight<distance[y])&&(!intree[y]))
{
distance[y]=p->weight;
parent[y]=w;
}
p=p->next;
}
int dis=INT_MAX;
for (int i=1;i<=g->nvertex; i++) {
if((distance[i]<dis)&&(!intree[i]))
{
dis=distance[i];
w=i;
}
}
cout<<parent[w]<<"->"<<w<<endl;
}
return trees;
}
当然。我这里是将点的访问顺序保存在一个vector里,然后就是返回,从以上代码可以看出,我们利用一行代码观察了最小生成树的生成过程。由于以上的算法都是对于每一个点都执行了|V|次,这里时间复杂度为O(n2)。