连通图的prim算法主要是求连通图的最小生成树。主要的思想是从图上某一点开始,找与之最近的(权重最小的)顶点,保存边和顶点。然后找与这两个点最近的(权重最小的)的顶点。循环往之,并每次保存边和边的顶点,就得到了最小生成树。
具体到算法的实现,根据参考资料,主要是两个数组,一个数组是保存当前未各顶点与已存顶点的最小距离lowcost,另一个一个数组是保存与之最小距离的顶点下标mst,比较并找寻最小的,然后将找到的顶点的lowcost清零(相当于剔除这个点),并根据新的顶点更新lowcost和mst。
这里我用前几天遍历的那个图随机赋值几个权重:
具体的求生成树的演算过程在电脑上写出来太烦了,我比较懒,就整理了我自己的演算草稿,贴图在下:
下面是实现的源代码,我就在前几天写的那个c++中的类添加了两个函数,然后将初始化的权重改了一下,在外部define了一个MAX_Weight。设置值为1000,当然还可以更大。
//prim求最短生成树,前提要是连通图
queue<int> Map::prim()
{
int minweight, minu;
queue<int> P;
int *lowcost = new int[VertexNum];
int *mst = new int[VertexNum];
mst[0] = 0;
//初始化
for (int i = 1; i < VertexNum; i++)
{
lowcost[i] = Edges[0][i];
mst[i] = 0;
}
for (int i = 1; i < VertexNum; i++)
{
minweight = MAX_Weight;//这里是1000
minu = 0;
for (int j = 1; j < VertexNum; j++)
{
if (lowcost[j] < minweight&& lowcost[j]!=0)
{
minweight = lowcost[j];
minu = j;
}
}
//分别push:边两个顶点的下标和边权值
P.push(mst[minu]);
P.push(minu);
P.push(minweight);
//push进的顶点置最大,表示不用更新它的权值了
lowcost[minu] = 0;
//如果新加入的点的权值小于之前的,则更新lowcost和mst
for (int j = 1; j < VertexNum; j++)
{
if (Edges[minu][j] < lowcost[j])
{
lowcost[j] = Edges[minu][j];
mst[j] = minu;
}
}
}
return P;
}
void Map::primout()
{
queue<int> P = prim();
while (!P.empty())
{
cout << P.front() << "-";
P.pop();
cout << P.front() << " :";
P.pop();
cout << P.front() << endl;
P.pop();
}
}
最后的输出结果如下: