普利姆算法实际上就是用一个数组存储最小生成树中的顶点,然后不断寻找这么一条边:边的一端是存在数组中的顶点,即最小生成树中的顶点,另一条边是最小生成树外的顶点,在满足这个条件下找到路径权值最小的边,并将边中原先并不在最小生成树中的顶点加入到最小生成树中,最终数组中的顶点即最小生成树的顶点数量等于图的顶点数量。
算法时间复杂度:0(n^2),适用于稠密图
#include <iostream>
#include <string>
using namespace std;
typedef struct Graph
{
string vertex[10];//顶点
int arc[10][10];//邻接矩阵
int num_vertex;//顶点数量
int num_edge;//边的数量
}Graph;
int get_location(Graph g, string s)//返回s在图中顶点数组的下标
{
int i;
for(i=0;i<g.num_vertex;i++)
{
if(s == g.vertex[i])
return i;
}
return -1;
}
void create_graph(Graph &g)//创建无向图
{
int i,j,k,w;
string s1,s2;
cout<<"请输入顶点数和边数:";
cin>>g.num_vertex>>g.num_edge;
cout<<"请输入顶点";
for(i=0;i<g.num_vertex;i++)
cin>>g.vertex[i];
for(i=0;i<g.num_vertex;i++)//别忘了给邻接矩阵初始化
for(j=0;j<g.num_vertex;j++)
g.arc[i][j]=65535;
cout<<"请输入边和对应的权值:"<<endl;
for(k=0;k<g.num_edge;k++)
{
cin>>s1>>s2>>w;
i = get_location(g,s1);
j = get_location(g,s2);
g.arc[i][j] = g.arc[j][i] = w;//邻接矩阵是对称矩阵
}
}
void minspantree_prim(Graph g)//最小生成树
{
cout<<"最小生成树各边为:"<<endl;
int i;
int lowcost[10];//lowcost数组保存相关顶点间的权值,如果其值为0,则说明该顶点加入到了最小生成树中
int adjvex[10];//保存顶点的前一个顶点的坐标,比如a->b的权值最小,则adjvex[b]=a
lowcost[0]=0;//初始化,将下标为0的顶点加入到最小生成树中,其实选取哪个顶点都可以
adjvex[0]=0;//初始化
for(i=1;i<g.num_vertex;i++)//初始化lowcost数组
{
lowcost[i] = g.arc[0][i];
adjvex[i] = 0;//到g.vertex[i]顶点的最小权值路径是由g.vertex[0]到达的。这只是初始化,后面还会进行更新
}
for(i=1;i<g.num_vertex;i++)//这里的i不代表顶点下标,而是代表循环的次数
{
int min = 65535;
int j,k;
for(j=1;j<g.num_vertex;j++)//在那些还没有加入到最小生成树中的顶点中找到lowcost中最小权值
{
if(lowcost[j]!=0 && lowcost[j]<min)//前提是lowcost[j]!=0,即其没有加入到最小生成树中
{
min = lowcost[j];
k = j;
}
}
cout<<g.vertex[adjvex[k]]<<"->"<<g.vertex[k]<<endl;//打印最小生成树的边
lowcost[k]=0;//将其加入到最小生成树中
for(j=1;j<g.num_vertex;j++)
{
if(lowcost[j]!=0 && g.arc[k][j]<lowcost[j])//更新lowcost的值,如果从顶点k出发的路径取值小于之前的权值,则进行更新
{
lowcost[j] = g.arc[k][j];
adjvex[j]=k;//更新adjvex,代表当前到这个节点的最小全值是从顶点k出发的
}
}
}
}
int main()
{
Graph g;
create_graph(g);
minspantree_prim(g);
return 0;
}
参考:http://blog.youkuaiyun.com/cxllyg/article/details/7603545