邻接表实现prim算法c语言,邻接表实现PRIM算法(C++)

参考张宪超老师《数据结构、算法及应用》

原理:

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值