Prim算法
输入:加权无向图G=(V,E)
输出:G的最小生成树
算法思想:
集合U,T,U放顶点,T放树边
选择有最小权的(u,v),且u ∈U,v∈V-U,,将u加入U,(u,v)加入T
重复这一过程直到U=V
void Prim(costtype C[n+1][n+1])
{
costtype LOWCOST[n+1]; //U与U-V中各一个顶点连成的具有最小权值的边
int CLOSEST[n+1];//U-V中的顶点 i对应的有最小权值的边的 U 中的 顶点 的编号
int i,j,k;
costtype min;
//默认1顶点一开始就在U中
for (int i=2;i<=n;i++)
{
LOWCOST[i]=C[1][i];
CLOSEST[i]=1;
}
for(int i=2;i<=n;i++)
{//找LOWCOST[]中最小的一个并记录下顶点编号k
min=LOWCOST[i];
k=i;
for (j=2;j<=n;j++)
{
if (LOWCOST[j]<min)
{
min=LOWCOST[j];
k=j;
}
}
cout<<"("<<k<<","<<CLOSEST[k]<<")"<<endl;
LOWCOST[k]=infinity;//恭喜k加入顶点集U
//infinity取一个很大的值
//更新顶点集U到U-V各点的最小权值
for (j=2;j<=n;j++)
if (C[k][j]<LOWCOST[j]&&LOWCOST[j]!=infinity)
{
LOWCOST[j]=C[k][j];
CLOSEST[j]=k;
}
}
}
复杂度:O(n2),适合顶点不多的图
Kruskal算法
输入:连通图G=(V,E)
输出:最小生成树
算法思想:
- 每个顶点自身为一个连通分量
- 按照边的权不减原则,依次考察E中每条边
- 若考察的边分属两个不同连通分量,则将这条边加入最小生成树T,合并两个分量。否则放弃这条边(避免生成环路)。
- 当整个图的连通分量数目为1时生成了一棵最小生成树
void Kruskal(EdgeSet edges,int n,int e)
{
int bnf,edf;
MFSET parents;
Sort(edges);//根据边不减原则排序
for (int i=1;i<=n;i++)
Initial(i,parents);//初始化每个顶点所在的连通分量
for (int i=1;i<=e;i++)
{
bnf=Find(edges[i].begin,parents);
edf=Find(edges[i].end,parents);
//若这条边的两个顶点不在同一连通分量
if (bnf!=edf)
{
Union(bnf,edf,parents);//合并为同一连通分量
//输出
cout<<"("<<edges[i].begin<<",";
cout<<edges[i].end<<","edges[i].cost<<")";
cout<<endl;
}
}
}
复杂度:时间复杂度O(E*log2E),适合求边稀疏的最小生成树