最小生成树
什么是最小生成树
- 是一棵树
- 无回路
- |V|个顶点一定有|V|-1条边 - 是生成树
- 包含全部顶点
- |V|-1条边全在图里
贪心算法
什么是“贪”:每一步都要最好的
什么是“好”:权重最小的边
需要约束:
- 只能用图里有的边
- 只能正好用掉|V|-1条边
- 不能有回路
普利姆(Prim)算法——让一棵小树长大
需要维护两个数组:lowcost[n] 、adjvex[n]
(n是图中的顶点数)
①从图中找第一个起始顶点v0,作为生成树的第一个顶点,然后从这个顶点到其他顶点的所有边中选一条权值最小的边。然后把这条边的另一个顶点v和这条边加入到生成树中。
②对剩下的其他所有顶点,分别检查这些顶点与顶点v的权值是否比这些顶点在lowcost数组中对应的权值小,如果更小,则用较小的权值更新lowcost数组。
③从更新后的lowcost数组中继续挑选权值最小而且不在生成树中的边,然后加入到生成树。
④反复执行②③直到所有所有顶点都加入到生成树中。
视频讲解
Void MiniSpanTree_Prim(MGraph G){
int min,i,j,k;
int adjvex[MAXVEX]; //保存邻接顶点下标的数组
int lowcost[MAXVEX]; //记录当前生成树到剩余顶点的最小权值
lowcost[0]=0; //将0号顶点(以0号顶点作为第一个顶点)加入生成树
adjvex[0]=0; //由于刚开始生成树只有一个顶点 不存在边 干脆都设为0
for(i=1;i<G.vexnum;i++){ //除下标为0以外的所有顶点
lowcost[i]=G.arc[0][i]; //将与下标为0的顶点有边的权值存入Lowcost数组
adjvex[i]=0; //这些顶点的adjvex数组全部初始化为0
}
//算法核心
for(i=1;i<G.vexnum;i++){//只需要循环N-1次,N为顶点数
min=65535; //tip:因为要找最小值,不妨先设取一个最大的值来比较
j=0;k=0;
//找出lowcost最小的 最小权值给min,下标给k
while(j<G.vexnum){ //从1号顶点开始找
if(lowcost[j]!=0 && lowcost[j]<min){ //不在生成树中的顶点而且权值更小的
min=lowcost[j]; //更新更小的值
k=j; //找到了新的点下标给k
}
j++; //再看下一个顶点
}
printf(“(%d->%d)”,adjvex[k],k); //打印权值最小的边
lowcost[k]=0; //将这个顶点加入生成树