Prim算法是求最小生成树的一种常见算法,简单谈一下笔者自己的理解。
算法思路
- 设已经确定的点集为P,初始为空。设还未确定的点集为Q,初始为该图所有点的集合。设已经确定的边为X,初始为空。
- 选取任意一点作为起始点,将该点添加到集合P中,并从Q中移除该点。
- 从P中找到一个点A,从Q中找到一个点B,使得2点之间的路径AB的权值最小。
- 将路径AB添加到X,将Q中的点B添加到集合P中,并从Q中移除该点。
- 重复3~4,直至所有点确定路径。
代码思路
- 采用邻接矩阵保存图。
- 创建一个临时数组lowcost,长度为总点数,用于表示当前时刻集合P与各点的距离。
例如lowcost[3]=m,3表示下标为3的点,当m为0表示该点已经在集合P中,即已经确定;当m为65535,表示该点与集合P暂时没有直接路径可到达;其他值表示该点与P可以直接通过一条连线到达,并且当前最短距离为m。
需要说明的是,这个数组是会不断变化的,最初,当P中只有一个点A的时候,lowcost表示A到各点的距离,这个时候有些点与点A没有直达路径,此时这些点是为65535的;而程序结束时,该数组的元素的值将都为0,因为所有点已经都添加到P了,此时各点到P的距离都为0。 - 创建临时数组mst,长度为总点数,用于保存步骤2的最短距离m对应的边关系。即每次添加一个点到P后,会更新P与剩余各点之间的最短距离m,此时会记录最短距离的边AB的起始点和结束点。
例如lowcost[3]=m,mst[3]=2表示下标为3的点A到P的距离为m,该连线是A与P中下标为2的点B的连线。 - 初始化:选取图的点集合的下标为0的点A,作为初始点。将图的边矩阵中,A与各点的距离(权重)写入lostcost数组作为初始值,并将mst各元素置零。创建临时变量n=1,表示已经确定的点数,用作循环结束的判断。
- 遍历lowcost数组,找出最小的值(排除0和65535),即当前集合P中任意一点到Q中任意一点的最短距离(权重)。记录下标minid。
- 将lowcost[minid]置为零,表示该点已经添加到P。
- 更新新添加到P的点minid与Q中各点的距离。即遍历图的边矩阵中起始点为minid的各元素,如果有比lowcost中对应元素的距离小的元素,则更新lostcost,同时更新mst。
例如,此时P中有3个点{A,B,C},Q中有2个点{D,E},C为刚刚添加的点。