//代码缩进有点难受,改了一下
关于最小生成树的算法,那么肯定要提到大名鼎鼎的prim和kruskal算法, 这两种算法思想大同小异。对于算法的学习,我的经验是搞懂思想,分模块去记忆,而不是去背代码,虽然短时间内,背代码确实可以较快的出程序,但是当算法非常多时,很容易混乱。
废话不多说,先说思想。
前提:边有权,连通图,采用邻接矩阵存储,因为我贪方便,所以无穷大就是未被赋值的一个负的随机值
Prim算法:( 三步走)
核心:
理解并掌握lowcost数组的意义(存放树的邻接边,如果有两条边指向同一个结点,那么存储较小的那一个)
1.(初始化)
初始化lowcost数组,将lowcost先初始化为v0结点的边的权值,此题为
代码为:
for (i = 0; i < graph->num; i++) {//初始化lowcost,treelowcost[i] = graph->vortex[0][i];tree[i] = 0;}
tree用于存放最小生成树,也先置0;
2.(寻找最小值)
现在我们已经知道了v0的周围一圈,那么我们就在这一圈里面找到最小的一条边,此题为v0到v2的边并把v2标记下来。然后把k收录进树,我们用lowcost=0来标记这个结点以及被收录进了树。
代码为:
for (i = 0; i < graph->num; i++) {//寻找lowcost最小值if (lowcost[i] < min && lowcost[i]>0){min = lowcost[i];k = i;}}lowcost[k] = 0;
3.(更新lowcost)
既然v2已经被收录进了树,v2也是有邻接点的,那么这棵树的邻接点也必须要改变(红色表示这棵树的邻接边,蓝色表示这棵树)
我们会发现,有两条边指向了同一个点,该如何取舍呢?
对的,找短的那条!
然后lowcost为
代码为:
for (i = 1; i < graph->num; i ++) {//更新lowcost[]的值并将i收进树if ((lowcost[i]<0||lowcost[i] > graph->vortex[k][i])&&graph->vortex[k][i]>0) {//和k有边连着.两种情况,1.比原来的权小,2.原来的权无lowcost[i] = graph->vortex[k][i];tree[i] = k;}}
完整代码给你们了:
void Prim(G* graph) {int lowcost[MAX], i, j, min, k;int tree[MAX];for (i = 0; i < graph->num; i++) {//初始化lowcost,treelowcost[i] = graph->vortex[0][i];tree[i] = 0;}for (j = 1; j < graph->num; j++) {//仅仅用于标记循环次数min = 32767;for (i = 0; i < graph->num; i++) {//寻找lowcost最小值if (lowcost[i] < min && lowcost[i]>0){min = lowcost[i];k = i;}}lowcost[k] = 0;for (i = 1; i < graph->num; i++) {//更新lowcost[]的值并将i收进树if ((lowcost[i]<0 || lowcost[i] > graph->vortex[k][i]) && graph->vortex[k][i] > 0) {//和k有边连着.两种情况,1.比原来的权小,2.原来的权为∞lowcost[i] = graph->vortex[k][i];tree[i] = k;}}}for (i = 0; i < graph->num; i++) {printf("%d ", tree[i]);}}}
到这里就完结了,win10的画图真不好用,画了半天还是好丑哦。