最小生成树算法之Prim算法
2015-01-29 23:56
309 查看
一、最小生成树
生成树是一个连通图(图中任意两个顶点都有路径相连)的极小连通子图,它含有图中所有顶点,但只有足以构成一棵树的n-1条边。最小生成树就是生成树中权值之和最小的生成树。最小生成树算法有Prim算法和 kruskal算法。
二、Prim算法
假设N=(V,{E})是连通图,V是顶点集合,{E}是边集,TE是N上最小生成树中边的集合。假设从顶点V0,(v0在V上)开始生成最小生成树,TE刚开始为空集。重复执行下述操作:在所有u(u属于已访问过的顶点,即是已在最小生成树内),v(在V-U内)的边(v,u)中找一条代价最小的边(u0,v0)并入集合TE,同时u0并入U,直到U=V为止,此时TE中必有n-1条边,则T=(V,{TE})为最小生成树。
根据算法的描述,该算法最要的两步是:
1.在所有u(u属于已访问过的顶点,即是已在最小生成树内),v(在V-U内)的边(v,u)中找一条代价最小的边(u0,v0)并入集合TE;
2.u0并入U;
图例分析:
根据Prim算法得到(假设从A开始)
1.(A,C),2(C,D),3(C,B),得到的最小生成树如下:
代码如下:
void MiniSpanTree_PRIM(MGraph *G,char v)
{
int k ,weight=0;
k=LocateVex(G,v);
//辅助数组初始化,与顶点k连接的边赋予其权值,不相连的为无穷大
for(int i=0;i<G->vexnum;i++)
{
if(i!=k)
{
closedge[i].adjvex=v;
closedge[i].lowcost=G->arcs[k][i].adj;
}
}
closedge[k].lowcost=0; //表示从顶点v开始生成最小生成树
for(int i=1;i<G->vexnum;i++)
{
//选择最小的边(一个顶点在已访问过的顶点中,一个不在)并入最小生成树
int min=INFINITY;
for(int j=0;j<G->vexnum;j++)
{
if(closedge[j].lowcost>0&&min>closedge[j].lowcost)
{
min=closedge[j].lowcost;
k=j;
}
}
cout<<"本次运行得到最小生成树的边为:"<<"("<<closedge[k].adjvex<<","<<G->vexs[k]<<")"<<endl;
closedge[k].lowcost=0;
weight+=min;
//更新closedge数组
for(int a=0;a<G->vexnum;a++)
{
if(G->arcs[k][a].adj<closedge[a].lowcost)
{
closedge[a].lowcost=G->arcs[k][a].adj;
closedge[a].adjvex=G->vexs[k];
}
}
}
cout<<"该最小生成树的权重为:"<<weight;
}
利用前面给出的图进行测试,结果如下:
最后,贴上CSDN内一大神写的Prim算法,将各个过程拆解开,分析的非常详细,而且代码风格相当好,地址:/article/1797676.html
点击打开链接
生成树是一个连通图(图中任意两个顶点都有路径相连)的极小连通子图,它含有图中所有顶点,但只有足以构成一棵树的n-1条边。最小生成树就是生成树中权值之和最小的生成树。最小生成树算法有Prim算法和 kruskal算法。
二、Prim算法
假设N=(V,{E})是连通图,V是顶点集合,{E}是边集,TE是N上最小生成树中边的集合。假设从顶点V0,(v0在V上)开始生成最小生成树,TE刚开始为空集。重复执行下述操作:在所有u(u属于已访问过的顶点,即是已在最小生成树内),v(在V-U内)的边(v,u)中找一条代价最小的边(u0,v0)并入集合TE,同时u0并入U,直到U=V为止,此时TE中必有n-1条边,则T=(V,{TE})为最小生成树。
根据算法的描述,该算法最要的两步是:
1.在所有u(u属于已访问过的顶点,即是已在最小生成树内),v(在V-U内)的边(v,u)中找一条代价最小的边(u0,v0)并入集合TE;
2.u0并入U;
图例分析:
根据Prim算法得到(假设从A开始)
1.(A,C),2(C,D),3(C,B),得到的最小生成树如下:
代码如下:
#define INFINITY INT_MAX //maximum #define MAX_VERTEX_NUM 20 //the maximum of vertex number typedef struct ArcCell{ int adj; //while the graph is unweighted ,adj is equal to 1 or 0.while the graph is weighted //,adj is equal to the weight of the arc. int *info; //the pointer of information about the arc }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { char vexs[MAX_VERTEX_NUM]; //the vector of vertex AdjMatrix arcs; //adjacent matrix int vexnum,arcnum; }MGraph; //用于prim最小生成树算法的辅助数组,clodedge[i-1].lowcost=Min{cost(u,vi)|u属于已经为最小生成树中的顶点} struct { char adjvex; int lowcost; }closedge[MAX_VERTEX_NUM];
//****************邻接矩阵表示***************** //********************************************* void CreatGraph2(MGraph *G);//邻接矩阵表示图 int LocateVex(MGraph G,char v);//确定顶点v在顶点向量中的位置 void MiniSpanTree_PRIM(MGraph *G,char v);//prim最小生成树算法
int LocateVex(MGraph *G,char v) { int k=0; for(int i=0;i<G->vexnum;i++) { if(v==G->vexs[i]) k=i; } return k; } void CreateGraph2(MGraph *G) { cout<<"请输入图的顶点数(顶点个数最大值为20):"<<endl; cin>>G->vexnum; cout<<"请输入图的弧的个数:"<<endl; cin>>G->arcnum; cout<<"请输入顶点编号构造顶点向量:"<<endl; for(int i=0;i<G->vexnum;i++) cin>>G->vexs[i]; cout<<"顶点向量构造完成!"<<endl; for(int i=0;i<G->vexnum;i++) for(int j=0;j<G->vexnum;j++) { //初始化邻接矩阵 G->arcs[i][j].adj=INFINITY; G->arcs[i][j].info=NULL; } cout<<"开始构造邻接矩阵!"<<endl; for (int i=0;i<G->arcnum;i++) { char v1,v2;//顶点编号 int k1,k2,w; cout<<"请输入该边的两个顶点v1、v2:"<<endl; cin>>v1>>v2; //确定v1,v2的位置 k1=LocateVex(G,v1); k2=LocateVex(G,v2); cout<<"输入该边的权值:"<<endl; cin>>w; G->arcs[k1][k2].adj=w; G->arcs[k2][k1].adj=G->arcs[k1][k2].adj; } cout<<"邻接矩阵构造完毕!"<<endl; }
void MiniSpanTree_PRIM(MGraph *G,char v)
{
int k ,weight=0;
k=LocateVex(G,v);
//辅助数组初始化,与顶点k连接的边赋予其权值,不相连的为无穷大
for(int i=0;i<G->vexnum;i++)
{
if(i!=k)
{
closedge[i].adjvex=v;
closedge[i].lowcost=G->arcs[k][i].adj;
}
}
closedge[k].lowcost=0; //表示从顶点v开始生成最小生成树
for(int i=1;i<G->vexnum;i++)
{
//选择最小的边(一个顶点在已访问过的顶点中,一个不在)并入最小生成树
int min=INFINITY;
for(int j=0;j<G->vexnum;j++)
{
if(closedge[j].lowcost>0&&min>closedge[j].lowcost)
{
min=closedge[j].lowcost;
k=j;
}
}
cout<<"本次运行得到最小生成树的边为:"<<"("<<closedge[k].adjvex<<","<<G->vexs[k]<<")"<<endl;
closedge[k].lowcost=0;
weight+=min;
//更新closedge数组
for(int a=0;a<G->vexnum;a++)
{
if(G->arcs[k][a].adj<closedge[a].lowcost)
{
closedge[a].lowcost=G->arcs[k][a].adj;
closedge[a].adjvex=G->vexs[k];
}
}
}
cout<<"该最小生成树的权重为:"<<weight;
}
void main() { char star; MGraph G1; CreateGraph2(&G1); cout<<"请输入要从哪个顶点开始生成最小生成树:"; cin>>star; MiniSpanTree_PRIM(&G1,star); }
利用前面给出的图进行测试,结果如下:
最后,贴上CSDN内一大神写的Prim算法,将各个过程拆解开,分析的非常详细,而且代码风格相当好,地址:/article/1797676.html
点击打开链接
相关文章推荐
- 一步一步复习数据结构和算法基础-prim算法(最小生成树)
- 最小生成树算法(类Prim算法的笨办法)
- 图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
- 十二、图的算法入门--(2)最小生成树---Prim算法实现
- 【算法导论】最小生成树(prim算法)
- 算法java实现--贪心算法--最小生成树问题--Prim算法
- Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)
- 浅谈最小生成树的算法思路(一)Prim算法
- 最小生成树算法 prim算法
- 最小生成树算法(类Prim算法的笨办法)
- 求解最小生成树的算法 prim算法(附模板)
- hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)
- 图论中最小生成树构造算法之Prim算法和Kruskal算法
- 最小生成树算法---普里姆Prim算法
- 最小生成树算法---普里姆Prim算法
- 无向图的最小生成树算法的C程序实现代码(Prim算法)
- 【算法导论】最小生成树(prim算法)
- 最小生成树算法-Prim算法
- 最小生成树算法之Prim算法
- 算法——最小生成树:Kruskal算法、Prim算法