参考张宪超老师《数据结构、算法及应用》
原理:
G=是一个连通的带权无向图。Prim算法通过不断地增加生成树的顶点来得到最小生成树。在算法的任一时刻,一部分顶点已经添加到生成树的顶点集合中,而其余顶点尚未加到生成树中。此时,Prim算法通过选择边,使得的权值是所有u(起点)在生成树中,但v(终点)不在生成树中的边的权值最小者,从而找到新的顶点v把她添加到生成树中。
详细步骤:
1)初始状态,U={u1},TE={}。其中,u1是图顶点集合的某一顶点。
2)在所有u∈U,v∈V-U的边(u,v)中寻找代价最小的边(u',v'),并纳入集合TE中;同时将v'纳入集合U中。确保这一过程中不产生回路。
3)如果u=v,则算法结束;否则重复2.
代码实现:
#include
#include
using namespace std;
class edge{
public:
int start;
int end;
int weight;
edge(int strt,int ed,int w){
start=strt;
end=ed;
weight=w;
}
edge(){
start=-1;
end=-1;
weight=-1;
}
};
//邻接表
class listnode{
public:
int listver;
int edgenam;
int weight;
listnode * next;
listnode(listnode * nextval=NULL){
next=nextval;
}
listnode(const int& lv,const int& en,const int &
w,listnode* nextval=NULL){
listver=lv;
edgenam=en;
weight=w;
next=nextval;
}
};
class headnode{
public:
listnode *start;
headnode(){
start=new listnode();
}
void removeall(){
listnode *tmp;
while(start!= NULL){
tmp=start;
start=start->next;
delete tmp;
}
}
~headnode(){
removeall();
}
};
class listgraph{
private:
headnode* gralist;
public:
int vertexnum;
int edgenum;
int *mark; //访问过为1,未访问为0;
listgraph(int n){
vertexnum=n;
edgenum=0;
mark=new int[vertexnum];
for(int i=0;i
mark[i]=0;
gralist=new headnode[vertexnum];
}
~listgraph(){
delete[]mark;
delete[]gralist;
vertexnum=0;
edgenum=0;
}
edge firstedge(int v){
edge tmpedge;
tmpedge.start=v;
listnode* tmplst=gralist[v].start;
if(tmplst->next!=NULL)
{
tmpedge.end=tmplst->listver;
}
return tmpedge;
}
edge nextedge(edge oneedge){
edge tmpedge;
tmpedge.start=oneedge.start;
listnode* tmplst=gralist[oneedge.start].start;
while(tmplst->next!=NULL&&tmplst->next->listver<=oneedge.end)
tmplst=tmplst->next;
if(tmplst->next!=NULL)
{
tmpedge.end=tmplst->next->listver;
}
return tmpedge;
}
void setedge(int strt,int end,int wt){
listnode* tmplst=gralist[strt].start;
while(tmplst->next!=NULL&&tmplst->next->listver
tmplst=tmplst->next;
//确定该边在边结点插入位置
//边在边结点中不存在
if(tmplst->next==NULL){
tmplst->next=new listnode;
tmplst->next->listver=end;
tmplst->next->edgenam=edgenum;
tmplst->next->weight=wt;
edgenum++;
setedge(end,strt,wt);
return;
}
//边在边结点中已存在
if(tmplst->next->listver==end){
edgenum--;
return;
}
//边在边结点中不存在,但在边表中其后存在其他边
if(tmplst->next->listver>end)
{
listnode* tmp=tmplst->next;
tmplst->next=new listnode;
tmplst->next->listver=end;
tmplst->next->edgenam=edgenum;
tmplst->next->next->weight=wt;
tmplst->next->next=tmp;
edgenum++;
setedge(end,strt,wt);
return;
}
}
void deledge(int start,int end){
listnode* tmplst=gralist[start].start;
while(tmplst->next!=NULL&&tmplst->next->listver
tmplst=tmplst->next;
if(tmplst->next==NULL){
cout<
return;
}
if(tmplst->next->listver==end)
{
listnode * tmp=tmplst->next->next;
delete tmplst->next;
tmplst->next=tmp;
edgenum--;
}
}
void show(int v){
cout<
if(gralist[v].start!=NULL)
{
listnode* tmp=gralist[v].start;
// cout<"<listver<
"<edgenam;
while(tmp->next!=NULL)
{
tmp=tmp->next;
cout<"<listver<
"<edgenam;
}
}
return;
}
void show(){
cout<
cout<
cout<
cout<
for(int i=0;i
{
show(i);
cout<
}
return;
}
void visit(int v){
cout<
}
edge * prim(int s){
int i,j;
edge *mst; //存储最小生成树的边
int *nearest; //nearest[i]表示生成树中点到i点的最小边""权值""
int *neighbor; //neighbor[i]表示生成树中与i点最近的""点编号"",
//-1表示i点已经在生成树集合中
int n=vertexnum;
nearest= new int[n];
neighbor=new int [n];
mst=new edge [n-1];
for(i=0;i
{
neighbor[i]=s;
nearest[i]=100;
}
for(listnode* tmp=gralist[s].start->next;tmp!=
NULL;tmp=tmp->next)
{
nearest[tmp->listver]=tmp->weight;
}
neighbor[s]=-1;//将已加入到生成树的点的最近邻设置成-1
for(i=1;i
//用i标记已经加入到生成树中的点个数
int min=100;
int v=-1;
for(j=0;j
//确定一个顶点在生成树集合一个顶点不在生成树集合且权值最小
//的边所关联的顶点
if(nearest[j]-1){
min=nearest[j];
v=j;
}
}
if(v>=0){
//将V加入到生成树集合中,更新生成树外的各个点最小权值的边信息
edge tempedge(neighbor[v],v,nearest[v]);
mst[i]=tempedge;//将边加入到生成树集合中
neighbor[v]=-1;
for(listnode*
tmp=gralist[v].start->next;tmp!=NULL;tmp=tmp->next){
int u=tmp->listver;
if(neighbor[u]!=-1&&nearest[u]>tmp->weight){
//用于V关联的边更新生成树之外顶点到生成树集合的最小权值边
neighbor[u]=v;
nearest[u]=tmp->weight;
}
}
}
}
delete[]neighbor;
delete[]nearest;
cout<
V"<
for(i=1;i
{
cout<
"<
"<
}
return mst;
}
};
int main(){
listgraph graph=listgraph(6);
graph.setedge(0,1,6);
graph.setedge(0,2,1);
graph.setedge(0,3,5);
graph.setedge(1,2,5);
graph.setedge(1,4,3);
graph.setedge(2,3,5);
graph.setedge(2,4,6);
graph.setedge(2,5,4);
graph.setedge(3,5,2);
graph.setedge(4,5,6);
graph.show();
graph.prim(1);
return 0;
}