一、普里姆(Prim)算法
1.基本思想:设G=(V, E)是具有n个顶点的连通网,T=(U, TE)是G的最小生成树, T的初始状态为U={u0}(u0∈V),TE={},重复执行下述操作:在所有u∈U,v∈V-U的边中找一条代价最小的边(u, v)并入集合TE,同时v并入U,直至U=V。即:
(1)从连通网络 G = { V, E }中的某一顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。
(2)以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合U中为止。
2.示例:
3.实现:
void MiniSpanTree_PRIM(MGraph G, VertexType u)
{
// 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。
// 记录从顶点集U到V-U的代价最小的边的辅助数组定义:
// struct {
// VertexType adjvex;
// VRType lowcost;
// } closedge[MAX_VERTEX_NUM];
k = LocateVex ( G, u );
for ( j=; j<G.vexnum; ++j )
{ // 辅助数组初始化
if (j!=k)
{ closedge[j].adjvex=u; closedge[j].lowcost=G.arcs[k][j].adj; }
}
closedge[k].lowcost = ; // 初始,U={u}
for (i=; i<G.vexnum; ++i)
{ // 选择其余G.vexnum-1个顶点
k = minimum(closedge); // 求出T的下一个结点:第k顶点
// 此时closedge[k].lowcost =
// MIN{ closedge[vi].lowcost | closedge[vi].lowcost>0, vi∈V-U }
printf(closedge[k].adjvex, G.vexs[k]); // 输出生成树的边
closedge[k].lowcost = ; // 第k顶点并入U集
for (j=; j<G.vexnum; ++j)
if (G.arcs[k][j].adj < closedge[j].lowcost)
{
// 新顶点并入U后重新选择最小边
closedge[j] = { G.vexs[k], G.arcs[k][j].adj };
}
}
}
二、克鲁斯卡尔(Kruskal)算法
1. 基本思想:设无向连通网为G=(V, E),令G的最小生成树为T=(U, TE),其初态为U=V,TE={ },然后,按照边的权值由小到大的顺序,考察G的边集E中的各条边。若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为G的一棵最小生成树。
2.示例:
3.实现:
. 初始化:U=V; TE={ };
. 循环直到T中的连通分量个数为1
2.1 在E中寻找最短边(u,v);
2.2 如果顶点u、v位于T的两个不同连通分量,则
2.2. 将边(u,v)并入TE;
2.2. 将这两个连通分量合为一个;
2.3 在E中标记边(u,v),使得(u,v)不参加后续最短边的选取;
未完待续,,,