最小生成树的两种方法Prim和Kruskal(C++)
最小生成树:n个顶点用n-1条最短的边连起来且不重复。
Prim算法——基本思想
图采用邻接矩阵存储
数组adjvex[n]:表示候选最短边的邻接点
数组lowcost[n]:表示候选最短边的权值
算法:Prim 输入:无向连通网G=(V,E) 输出:最小生成树T=(U,TE)
- 初始化:U = {v}; TE={ };
- 重复下述操作直到U = V:
2.1 在E中寻找最短边(i,j),且满足i∈U,j∈V-U;
2.2 U = U + {j};
2.3 TE = TE + {(i,j)};
void Prim(int v) //从顶点v出发
{
int i, j, k;
int adjvex[MaxSize], lowcost[MaxSize];
for (i = 0; i < vertexNum; i++) //初始化辅助数组
{
// 先把与v相邻的边赋值到lowcost中, 在lowcost中寻找最短边
lowcost[i] = edge[v][i]; adjvex[i] = v;
}
lowcost[v] = 0; //将顶点v加入集合U,lowcost[i]=0;表示将其加入到U中 U={v,i}
for (k = 1; k < vertexNum; k++) //迭代n-1次
{
j = MinEdge(lowcost, vertexNum);//寻找最短边的邻接点j
cout << "(" << vertex[j] << "," << vertex[adjvex[j]] << ")" << lowcost[j] << endl;
lowcost[j] = 0; //顶点j加入集合U,本身到本身的距离为0
for (i = 0; i < vertexNum; i++) //调整辅助数组
if (edge[i][j] < lowcost[i]) {
//将j[新增点]的相连边的距离更新到lowcost
lowcost[i] = edge[i][j];
adjvex[i] = j;
}
}
}
Kruskal算法
【注意先对边集合edge[i]进行排序,让最短边先开始Kruskal】
【这是个坑,不然会按照你输入边的顺序进行Kruskal】
算法:Kruskal算法 输入:无向连通网G=(V,E) 输出:最小生成树T=(U,TE)
1. 初始化:U=V;TE={ };
2. 重复下述操作直到所有顶点位于一个连通分量:
2.1 在E中选取最短边(u,v);
2.2 如果顶点 u、v 位于两个连通分量,则
2.2.1 将边 (u,v) 并入TE;
2.2.2 将这两个连通分量合成一个连通分量;
2.3 在 E 中标记边 (u,v),使得 (u,v) 不参加后续最短边的选取;
void Kruskal( )
{
int num = 0, i, vex1, vex2;
int parent[vertexNum]; //双亲表示法存储并查集
for (i = 0; i < vertexNum; i++)
parent[i] = -1; //初始化n个连通分量
for (num = 0, i = 0; num < vertexNum - 1; i++)//依次考察最短边
{
vex1 = FindRoot(parent, edge[i].from);
vex2 = FindRoot(parent, edge[i].to);
if (vex1 != vex2) {
//位于不同的集合
cout << "(" << vertex[edge[i].from]<< "," << vertex[edge[i