【算法导论03】贪心算法-prim算法

03贪心算法-prim算法


问题描述:
给出一个带权无向图,请设计一个算法,找出其中的最小生成树。

思路分析:
贪心算法的本质是:一个问题的局部最优解,也是该问题的全局最优解。接下来来了解一下最小生成树的最优子结构性质:假设一个无向图包含两部分A,B,其中A为最小生成树部分,B为剩余部分,则存在以下性质:该无向图中一个顶点在A部分,另一个顶点在B部分的边中,权值最小的边一定属于整个无向图的最小生成树,即部分最小权值是整个最小生成树的局部最有解,该性质符合贪心算法的特点。基于最小生成树的该性质,使用prim算法来求解最小生成树。

笔记:(-from MIT算法导论课程)
在这里插入图片描述
在这里插入图片描述

算法思路:
设置两个数组1,2,数组1存放当前顶点到其他所有顶点的边的权值(若没有边就设为∞),数值下标即为对应顶点序号,如min_weight[2]=3代表当前顶点到序号为2的顶点的边的权值为3。数组2用于存放哪个顶点到该顶点,如adjvex[2]=5表示,顶点2由5指出。两个数组相互配合,可以实现记录任意顶点到其他边的权值。
算法核心思想为利用一个循环,判断所有已经加入最小生成树的顶点到其他顶点(该顶点没有加入最小生成树)的边的距离,并找出其中的最小值,将该顶点加入最小生成树中,与此同时,对数组1进行更新(即当前顶点已经发生改变),并对数组2进行更新(即指向当前顶点的点已经发生改变),最终实现最小生成树。

prim算法代码:

void MST_prim(graph g){
	int min_weight[g.vexnum]//该点到g.vexnum的距离
	int adjvex[g.vexnum]//由哪个点到g.vexnum
	for(int i=0;i<g.vexnum;i++){//初始化数组
		min_weight[i] = g.edge[0][i];
		adjvex[i] = 0;
	}

int min_arc;//weight中的最小边权值
int min_vex;//当前顶点

for(int i=1;i<g.vexnum;i++){//对剩余对n-1个顶点进行循环
	min_arc = MAX;//
	for(int j=1;j<g.numvex;j++)//找最小边的顶点
		if(min_weight[j]!=0&&min_weight[j]<min_arc){//!=0表示顶点不在生成树中,min是上一个顶点到该点的边最小权值
			min_arc = min_weight[j];
			min_vex = j;//方便下面对该点标记已加入
		}
	min_weight[min_vex] = 0;//表示当前顶点已经加入最小生成树
	for(int j=0;j<g.vexmin;j++){//修改辅助数组1,将该最小顶点到其他边的距离加入进去,同时修改辅助数组2
		if(min_weight[j]!=0&&g.edge[min_vex][j]<minweight[j]){
			min_weight[j] = g.edge[min_vex][j];//将找到的最小边点到其他点j的距离给min_weight[j]数组
			adjvex[j] = min_vex; //将已经修改的点的辅助数组2中的值修改为该最小边点
		}
	}
}
}
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值