[算法学习no13]prim算法

普利姆算法
数据结构:
1.pick数组,代表是否被选中
2.mindis数组,下标就是点的编号,数值为当前已选点的集合中的所有点到这个点的距离的最小值
3.father数组,下标也是点的编号,如果该点没有选定,则为-1,否则为更新mindis时对应路径和其相连的点的编号
步骤:
1.接入一个顶点
2.遍历和这个顶点相连的所有边,拿出相连的顶点,(如果该顶点没有被选中)到mindis里面进行比较
如果小于,则更新相应的mindis和father,并且和当前最小值min进行比较,如果还是小于,那么记录当前点的编号,更新min
3.遍历完这个顶点之后,拿出记录的最小路径编号,把这个编号的pick改为1说明选中
4.按照上述路径再对这个顶点进行处理即可。
由于我们需要遍历和一个点相连的所有边,所以用链式前向星
对于链式前向星的遍历细节,请到我的[数据结构No1]中查看详情
prim算法需要先判断是否是连通图再做决定
而且创建图时,应该设置为无向边,也就是起点终点呼唤设置两条边
如果起点终点相同那么可以直接跳过
如果重边其实也不需要管,因为prim算法会把和结点所有相连的最小边找出来
细节问题:
一般从node=1开始进行遍历,但是别忘了pick[1]=1;也就是先把第一个点标记再进行下面的步骤

void prim()
{
	cnt=0;
	int tmp;
	pick[node]=1;
	while(1)
	{
		min=inf;
		//遍历和node相连的结点和他们之间的距离
		for(int i=head[node];i;i=edge[i].nextEdge)//i是边的下标,head[node]即和node相连的第一条边的下标 
		{
			tmp=edge[i].endNode;//和node相连的结点 
			if(pick[tmp]==0)//该节点还没有被选中 
			{
				if(mindis[tmp]>edge[i].dis)//比较当前已存在边和当前结点的距离 
				{
					//如果当前的tmp更小,那么更新mindis和father里面的值 
					mindis[tmp]=edge[i].dis;
					father[tmp]=node;
				}
			}
		}
		//开始找到已经储存的点里面最短的边 
		for(int i=1;i<=n;i++)
		{
			if(pick[i]==0&&mindis[i]!=inf)//从还没有pick的点并且可以到达的边里面挑选 
			{
				if(mindis[i]<min)//如果当前结点边小于min值,更新min值,并记录结点编号 
				{
					min=mindis[i];
					minnode=i;
				}
			}
		}
		//找到所需结点之后,直接选定,并且更新下次要寻找的node为当前的node 
		pick[minnode]=1;
		node=minnode;
		cnt++;
		if(cnt==n)
		{
			break;
		}
		sum=sum+min;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值