prim算法生成最小生成树(邻接表建图)

# include<iostream>
# include<cstring>
using namespace std;
# define inf 0x3f3f3f3f
# define nil -1
const int maxn=100+5;
typedef struct arcnode{
	int adjnode;
	int weight;    //边的权重 
	arcnode *nextarc;
}arcnode;
typedef struct vnode{
	int data;    //顶点信息 
	arcnode *firstarc;
}vnode;
typedef struct graph{
	vnode vertexs[maxn];
	int vertexnum;
	int edgenum;
}graph;
struct closeedge {
	int adjvex;
	int lowcost;
};

int find(graph g,int v)
{
	for(int i=0;i<g.vertexnum;i++)
	   if(g.vertexs[i].data==v)
	       return i;
	return -1;
}
void init(graph &g)   //建图,并初始化 
{
	cin>>g.vertexnum>>g.edgenum;
	for(int i=0;i<g.vertexnum;i++)
	{
	  	cin>>g.vertexs[i].data;  
	  	g.vertexs[i].firstarc=NULL;
	  }
	for(int i=0;i<g.edgenum;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		int index_u=find(g,u);
		int index_v=find(g,v);
		
		arcnode *s=new arcnode();
		s->adjnode=index_v;
		s->weight=w;
		s->nextarc=g.vertexs[index_u].firstarc;
		g.vertexs[index_u].firstarc=s;
		
		arcnode *p=new arcnode();
		p->adjnode=index_u;
		p->weight=w;
		p->nextarc=g.vertexs[index_v].firstarc;
		g.vertexs[index_v].firstarc=p;
		
	}
}
int makeit(graph g,int u,int i)   //如果有从u->i的无向边,则返回对应权值,否则返回最大值 
{
	arcnode *s;
	s=g.vertexs[u].firstarc;
	while(s)
	{
		if(s->adjnode==i)
		  return s->weight;
		s=s->nextarc;
	}
	 return inf;
}
int minedge(closeedge *w,graph g)  //取最小边的索引 
{
	int index_min;
	int min_cost=inf;
	for(int i=0;i<g.vertexnum;i++)
	{
		if(w[i].lowcost>0&&min_cost>w[i].lowcost)  //w[i].lowcost=0表示该顶点已加入最小生成树的顶点集合中。 
		{
			min_cost=w[i].lowcost;
			index_min=i;
		}
		
	}
	return index_min;
}
void prim(graph g,int u,closeedge *w)
{
	int index_u=find(g,u);
	 for(int i=0;i<g.vertexnum;i++)  //初始化,初始顶点到各个顶点的距离 
	 {
	     if(i!=index_u)
	   {
	      w[i].adjvex=u;
	      w[i].lowcost=makeit(g,index_u,i);   
		}
	}
	 w[index_u].lowcost=0;  //加入生成树顶点集合 
	for(int i=1;i<g.vertexnum;i++)
	{
		index_u=minedge(w,g);//取最小边的索引 
		cout<<"(v"<<w[index_u].adjvex<<",v"<<g.vertexs[index_u].data<<") ";
		w[index_u].lowcost=0;  //加入生成树顶点集合
		for(int j=0;j<g.vertexnum;j++)   //加入以index_u为索引的顶点,并更新w数组,在 
		{
			int m=makeit(g,index_u,j);   //得到index_u到j的权值 
		   if(m<w[j].lowcost)      //比较,并更新 
		   {
		   	  w[j].adjvex=g.vertexs[index_u].data;
		   	  w[j].lowcost=m;
			   }	
		}
	}
}

int main()
{
	int u;
	closeedge w[maxn];
	graph g;
     init(g);
     cin>>u;
	 prim(g,u,w);	
	return 0;
 } 

总结:
(1)在最小生成树未建成时,一直在维护两个顶点集合,一个是生成树顶点集合s1,另一个是图中的顶点但未在生成树顶点集合中的集合s2,每次都需要从s2中挑出一个到s1的某个顶点的边的权值最小值的顶点加入s1;

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值