本节介绍了普利姆Prim算法的形成思路与代码解析,重点讲述了其中的如何引入lowcost列表以及closet列表,以及它们的作用和更新步骤。最后我依照代码解释了每一行代码的作用。
具体的代码如下:
#我觉得这代码多少有点问题,因为最终只输出了一步
def Prim(g,v):#g是图,并且此图采用邻接矩阵存储结构(因为Prim算法频繁的调用顶点的序号,所以Prim算法的图采用邻接矩阵的存储形式,因为采用邻接矩阵的存储结构,所以适合与稠密图)
#为两个以未接入点的集合出发的列表设置存储空间
lowcost=[0]*MAVV#用于判断未接入的这个顶点到接入的所有顶点的最小权值的边
closest=[0]*MAXV#用于在最后接入时告诉你接入的这个点应该连已经接入的哪个顶点
#给lowcost和closest置初始值,就是以v作为开始顶点lowcost和closet
for i in range(g.n):
#圈内只有一个点v,圈外往圈内连点最多只可能有一条,所以就把lowcost设置为这个,并且圈外的每一个顶点都有lowcost
lowcost[i]=g.edges[v][i]#与v相连的每一个圈外的点,自己到自己已经是0了,后来就舍弃掉了
closest[i]=v#现在圈内只有一个点,所以只能连v
#因为lowcost始终记录的是圈外的点到圈内的点的边的权的最小值,所以我们可以用不断更新最小值的方法来获取圈外每一个顶点到圈内的边的最小值
#不断比较lowcost从而获得min
#我们在执行过程中发现,一旦连入了一个点,那么只要把这个点到圈内所有元素的值与之前的lowcost进行比较取小就可以,这样可以不断更行lowcost的最小值
for i in range(1,g.n):#遍历所有的顶点,因为后来有判断lowcost[j]!=0,所以已经接入的点不再被判断
min=INF#给min设置一个初始值,其实设置成一个合适的就行,因为后来要找出最小的那条边
k=-1#k用来标记应该接入的顶点的序号
for j in range(g.n):#先对开始结点v进行操作
if lowcost[j]!=0 and lowcost[j]<min:#只要不是已经接入的顶点(lowcost[j]!=0)而且是权值比最小值大的点就接入
min=lowcost[j]#找到最小的权
k=j#标记应该接入的圈外顶点
print("(%d,%d):%d"(closet[k],k,+min),end='')#输出原来在圈内的顶点,应该接入的顶点,这条边的权值
lowcost[k]=0#把这个接入的顶点标记为已经接入
for j in range(g.n):#每接入一个新点,圈外的点减少一个,圈内的点增加一个,这样导致圈外的点到圈内的点的最短边发生变化,实际上只要立足于每一个圈外的点
#找到每一个圈外的点到新加的圈内点的边,只有新出现的边小于了原来每一个圈外边的lowcost,每个边的lowcost和对应的closet才会更新
if lowcost[j]!=0 and g.edges[k][j]<lowcost[j]:
lowcost[j]=g.edges[k][j]
closest[j]=k