理解prim(普里姆算法)——图的最小生成树

来源:互联网 发布:免费ppt模板下载 知乎 编辑:程序博客网 时间:2024/05/21 05:57



首先是算法的思想,

当时我接触到这个思想的时候,,我第一个想法是普里姆太牛逼了。。。。


这个算法的主要目的是有一个乱七八糟的图,我们要连通这些顶点  并且在其中找到一个的边的权重最小和

第一步 我们要找到一个顶点,,并且把它最小的边找到,然后连接,,现在我们有两个顶点

这两个顶点,在所有对外连接的边里,找到一个最小的并连接,这样我们就有了三个点

......

......

......


所以,我们在构建数据结构的时候,就要考虑到一个方便这个思想展开的结构,这里我们选择邻接矩阵表示图(我记得只有图的拓扑排序的时候采用邻接表)



背景:

图的顶点数量: vertexSize

邻接矩阵: matrix[][]

两个顶点没有连接的时候, 我们就规定 这个时候,这个假象边的值为1000,int nonMatrix = 1000,


顺着这个算法思路走,我们可以很容易想到,需要一个最小花费数组来记录每条边的状态 ,并且将第一个顶点v0的边的权重记录下来

int[] lowcost[vertexSize]   //  这个最小花费数组是整个算法的核心,,,,我们可以通过这个数组做两个事情,1  记录现有的通向 还未连接上的顶点  的边   的权重

for(int i = 0 ; i<vertexSize ; i++ ){

lowcost[i] = matrix[0][i]

}

之后我们开始循环遍历所有的顶点,并且在每一次遍历的时候,我们在lowcost中

for(int i = 1 ; i<vertexSize ; i++){  // 这里从1开始的原因是,我们在上边初始化的时候,已经把第一个顶点加进了lowcost数组中,这里就不用考虑邻接矩阵的第一行了

在这个遍历过程中,首先我们需要把lowcost里最小的那条边找到,所以我们需要一个int min, 

和这个被连接顶点的id  int minId (这两个变量应该在这个循环体外边声明,我为了方便理解,我们的思路到这里的时候,我们就需要这两个变量来记录了!!所以我写在这里)

min  = nonMatrix; // 这里,,可以这么解释,如果想让min记录最小的边的权重,那我们就需要初始化的时候,给他赋予一个 在这个算法中,最大的值

minId = 0;


在循环遍历所有顶点的过程, 我们要用一个循环来的出现在我们所确定连接的顶点,对外连接的边中,最小的那个

for(int  j = 1 ; j<vertexSize; j++){

if(lowcost[j] != 0 && lowcost[j] < min){

min = lowcost[j] ;

minId = j ;

}

}

这个时候我们就找到了现在我们已连接顶点四周,对外还没有连接顶点的边中,最小的那个边,和它连接到的顶点

所以我们把这个边的权重记录下来,

sum += min ;  // 这个sum 也是在开始就应该定义好的,我为了减少大家,,脑细胞并发率,,就写在这了

lowcost[minId] = 0; // 这里非常重要,通过这个记录,我们就可以将已找到的顶点去掉


 此时 我们已经找到了下一步我们要连接的顶点了

下面要做的,就是循环遍历这个新的顶点对外连接的边,并且添加到我们的lowcost数组中,当一个顶点,已经有边与其相连的时候,我们用if语句 将小的那一条边记录在数组内


for(int j = 1 ; j<vertexSize ; j++){

if(lowcost[j] != 0 && lowcost[j] >matrix[minId][j]{

lowcost[j] = matrix[minId][j] ;

 然后再继续迭代


}

}