最小生成树:无向图G的最小生成树是连接G的所有顶点的边构成的树,并且总价值最低,最小生成树存在当且仅当图是连通的。最小生成树不是唯一的,它是树,因为无圈;是生成树,因为包含每一个顶点。有两种算法
1.Prim算法
是贪婪算法,分步进行,每一步,都把一个顶点当作根加入树中。在每个阶段,有一个已知顶点的集合,其余顶点未知,选择未知顶点中到已知顶点集中距离最短的,声明为已知并加入到树中,代码如下:
/* 最小生成树的Prim算法 */
void Prim()
{
Vertex V, W;
for (;;)
{
V = smallest unknown distance vertex;
if (V == NotAVertex)
break;
for each W adjacnet to V
if (!T[W].Known)
/* 这个判断条件和dijkstra算法不同,不用考虑历史路径长度 */
if (Cvw < T[W].Dist)
{
Decrease(T[W].Dist to Cvw);
T[W].Path = V:
}
}
}
和Dijkstra算法思想是一样的,只是更新时候判断条件不同
2.Kruskal算法
是贪婪算法,和Prim算法的区别是,每个阶段贪婪的是最小的边,而不是距离最短的未知顶点,只要贪婪的边不产生圈,就加入进来。Kruskal算法基于的基础数据结构是不相交集,代码如下:
/* 最小生成树的Kruskal算法 */
void Kruskal(Graph G)
{
int EdgeAccepted;
DisjSet S;
PriorityQueue H;
Vertex U, V;
SetType Uset, Vset;
Edge E;
/* 将顶点存入到不相交集中 */
Initialize(S);
/* 将图中每条边读入优先队列中 */
ReadGraphIntoHeapArray(G, H);
BuildHeap(H);
EdgeAccepted = 0;
while (EdgeAccepted < NumVertex - 1)
{
/* 从优先队列中找最小的边,U和V是这个边的两个顶点 */
E = DeleteMin(H);
Vset = Find(U, S);
Uset = Find(V, S);
/* 若两个顶点不在一个集合中,那么说明有一个顶点不在树种,合并,否则已经在了,继续找
* 下一个最小的边*/
if (Uset != Vset)
{
EdgeAccepted++;
SetUnion(S, Uset, Vset);
}
}
}
最坏时间是