基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:
在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。
此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。
Prim算法的核心:始终保持TE中的边集构成一棵生成树。
//:Prim算法: Prim.cpp
//最小生成树算法
//2014-08-14
#include<iostream>
#include<queue>
using namespace std;
const int MAXVEX=100;
const int INFINITY=65535;
struct MGraph{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
};
void CreatMGraph(MGraph* G)
{
if(G==NULL)
{
return;
}
cout<<"Please input numVertexes and numEdges: "<<endl;
cin>>G->numVertexes>>G->numEdges;
//初始化顶点表
for(int i=0; i<G->numVertexes; ++i)
{
cout<<"Please input Vertex's data: "<<endl;
cin>>G->vexs[i];
}
//初始化邻接矩阵
for(int i=0; i<G->numVertexes; ++i)
{
for(int j=0; j<G->numVertexes; ++j)
{
if(i==j)
{
G->arc[i][j]=0;
}
else
{
G->arc[i][j]=INFINITY;
}
}
}
//创建邻接矩阵
int tailVex, headVex, weight;
for(int i=0; i<G->numEdges; ++i)
{
cout<<"Please input tailVex and headVex and weight: "<<endl;
cin>>tailVex>>headVex>>weight;
G->arc[tailVex][headVex]=weight;
G->arc[headVex][tailVex]=weight;
}
}
void Prim(MGraph* G)
{
if(G==NULL)
{
return;
}
int adjvex[MAXVEX];
int lowcost[MAXVEX];
adjvex[0]=0;
lowcost[0]=0;//lowcost[i]为0表示下标i对应的顶点已经加入最小生成树集合
for(int i=1; i<G->numVertexes; ++i)
{
lowcost[i]=G->arc[0][i];
adjvex[i]=0;//此时所有的顶点的邻接点为下标为0的顶点
}
for(int i=1; i<G->numVertexes; ++i)//控制循环次数,共需要G->numVertexes次循环将所有的顶点加入最小生成树集合中
{
int min=INFINITY;
int k=1;
for(int j=1; j<G->numVertexes; ++j)
{
if(lowcost[j]!=0&&lowcost[j]<min)//lowcost[j]!=0表示没有加入最小生成树集合的顶点
{
min=lowcost[j];
k=j;
}
}
cout<<"Edge is from "<<adjvex[k]<<" to "<<k<<endl;
lowcost[k]=0;//将k加入最小生成树集合
for(int j=1; j<G->numVertexes; ++j)
{
if(lowcost[j]!=0&&G->arc[k][j]<lowcost[j])
{
lowcost[j]=G->arc[k][j];
adjvex[j]=k;//此时顶点j的邻接点为下标为k的顶点;
}
}
}
}
int main()
{
MGraph* G=new MGraph;
CreatMGraph(G);
Prim(G);
delete G;
return 0;
}