鉴于网上的一些博客看的太难受了,于是想借着自己的理解写一篇关于prim算法。
首先先贴出将要具体的例子的图:
先定义一个数组:
int[] flags = new int[6];
int bianshu = 0;//变得数量 这个值应该是节点数减1
//初始化全为0
for(int i:flags)
i = 0;
首先随机的挑一个点,如挑选0号点。
然后将flags[0]置1。
此时flags=【1,0,0,0,0,0】
如图:
遍历flags中所有为1的节点,获取他们的邻边。如现在flags里只有id为0的为1,即flags[0] = 1;
0号节点的邻边为0 1 6,0 2 1,0 3 5,取出他们中最小的那么将会是0 2 。
随后将flags[2] = 1;
此时flags=【1,0,1,0,0,0】
bianshu++;
此时bianshu = 1
如果bianshu==节点数-1,那么此时就可以退出了。
如图
同第一个节点的做法,在flags中查看值为1 的所有的邻边,如
0号节点的所有临边为0 1 6 ,0 2 1,0 3 5,由于0号节点和2号节点在flags中的位置已经被置为1,所以将0 2 1这个边去掉,只剩下0 1 6,0 3 5.
二号节点的所有临边为2 0 1 ,2 1 5, 2 3 5,2 4 6, 2 5 4.由于0号节点和2号节点在flags中的位置为1,所以将2 0 1去掉。
然后在两个节点的所有的临边中取最小的那条边可以知道是2 5 4,这条边。
所以将flags[5] = 1;
此时flags = 【1,0,1,0,0,1】
bianshu++;
此时bianshu = 2
如果bianshu==节点数-1,那么此时就可以退出了。
如图:
同理现在找出flags中所有为1 的节点的所有领边,这一次我将会直接去掉一条边的两个节点在flags中都为1的情况:
0号节点的所有的邻边:0 1 6 , 0 3 5.
2号节点的所有的临边:2 1 5, 2 4 6,2 3 5.
5号节点的所有的邻边:5 4 6,5 3 2.
可以看到5 3 2 这条边的值最小为2.
所以flags[3] = 1;
此时flags =【1,0,1,1,0,1】
bianshu++;
此时bianshu = 3
如果bianshu==节点数-1,那么此时就可以退出了。
如图:
此时按照虚线可以看到有一条路径:
0–>2–>5–>3
此时按照上面的做法找出现有的所有flags中值为1 的所有节点的邻边:
0号节点的所有的邻边:0 1 6
2号节点的所有的邻边:2 1 5 , 2 4 6
5号节点的所有的邻边:5 4 6
3号节点的所有的临边:没有
此时可以看出2 1 5最小
所以flags[1] = 1;
此时flags = 【1,1,1,0,1】
bianshu++;
此时bianshu = 4
如果bianshu==节点数-1,那么此时就可以退出了。
如图:
同理找出flags中值为1 的所有节点的邻边:
0号节点的所有的邻边:没有
1号节点的所有的临边:1 4 3
2号节点的所有的邻边:2 4 6
3号节点的所有的邻边:没有
5号节点的所有的邻边:5 4 6
所以此时可以一目了然的知道1 4 3最小。
所以flags[4] = 1;
此时flags = 【1,1,1,1,1,1】
bianshu++;
此时bianshu=5 == 节点数-1,此时就可以退出了。
如图:
此时去掉图中的实线部分:
就可以得到一个最小的生成树了。
关于图的最小数的另一个算法觉得另一篇博客讲的不错,直接粘出来
https://www.cnblogs.com/wuxiangnong/p/10885129.html
里面有涉及并查集的部分可以查看我的另外一篇博客:
https://blog.csdn.net/qq_30761967/article/details/105208340