Prim算法
1.概览
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点
2.算法简单描述
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
下面对算法的图例描述
| 图例 | 说明 | 不可选 | 可选 | 已选(Vnew) |
|---|---|---|---|---|
|
|
此为原始的加权连通图。每条边一侧的数字代表其权值。 | - | - | - |
|
|
顶点D被任意选为起始点。顶点A、B、E和F通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 | C, G | A, B, E, F | D |
|
|
下一个顶点为距离D或A最近的顶点。B距D为9,距A为7,E为15,F为6。因此,F距D或A最近,因此将顶点F与相应边DF以高亮表示。 | C, G | B, E, F | A, D |
![]() |
算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 | C | B, E, G | A, D, F |
|
|
在当前情况下,可以在C、E与G间进行选择。C距B为8,E距B为7,G距F为11。E最近,因此将顶点E与相应边BE高亮表示。 | 无 | C, E, G | A, D, F, B |
|
|
这里,可供选择的顶点只有C和G。C距E为5,G距E为9,故选取C,并与边EC一同高亮表示。 | 无 | C, G | A, D, F, B, E |
|
|
顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG。 | 无 | G | A, D, F, B, E, C |
|
|
现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 | 无 | 无 | A, D, F, B, E, C, G |
定义一个图
GraphArr = [
[0, 6, 1, 5, MAX_NUM, MAX_NUM],
[6, 0, 5, MAX_NUM, 3, MAX_NUM],
[1, 5, 0, 5, 5, 4],
[5, MAX_NUM, 5, 0, MAX_NUM, 2],
[MAX_NUM, 3, 6, MAX_NUM, 0, 6],
[MAX_NUM, MAX_NUM, 4, 2, 6, 0],
]

PS:画的不是很好 哈哈 意思是这样子的
‘‘‘
最小生成树 prim算法
普里姆(Prim)算法:由线到点,适合边稠密。时间复杂度O(N^2)
‘‘‘
Debug_P = 0
V_NUM = 6
MAX_NUM = 10000
GraphArr = [
[0, 6, 1, 5, MAX_NUM, MAX_NUM],
[6, 0, 5, MAX_NUM, 3, MAX_NUM],
[1, 5, 0, 5, 5, 4],
[5, MAX_NUM, 5, 0, MAX_NUM, 2],
[MAX_NUM, 3, 6, MAX_NUM, 0, 6],
[MAX_NUM, MAX_NUM, 4, 2, 6, 0],
]
# U放已经匹配好的顶点:
U = []
# V初始化为所有顶点的集合:
V = []
# T放各个边:
T = []
def init():
if(Debug_P):
print("GraphArr = ", end = "")
print(GraphArr)
i = 0
while i < V_NUM:
V.append(i+1)
i = i+1
def prim_start_vertex(start):
if(start < 1):
print("ERROR: start = ", start)
print("ERROR: change start to 1 by default")
start = 1
U.append(start)
del V[start-1]
def list_sort(list):
if(len(list) < 1):
print("ERROR: Len Of List = ", len(list))
exit(1)
index = 0
i = 0
min_val = list[0]
while i < len(list):
if min_val > list[i]:
min_val = list[i]
index = i
i = i+1
if(Debug_P):
print("[list_sort]: list = ", list, ", index = ", index)
return index
def min_wui():
m = MAX_NUM
close_edge = {‘u‘:-1, ‘v‘:-1}
edge_list = []
vertex_list = []
i = 0
j = 0
# 算出U和V之间所有边的长度:
lu = len(U)
lv = len(V)
if(Debug_P):
print("########### entry min_wui ###########")
print("lu = ", lu,", lv = ", lv)
while i < len(U):
while j < len(V):
if(Debug_P):
print("i = ", i, "j = ", j)
print("U[i] = ", U[i], ", V[j] = ", V[j])
temp = GraphArr[ U[i]-1 ][ V[j]-1 ]
if(temp > 0):
if(temp < MAX_NUM):
close_edge = {‘u‘:U[i], ‘v‘:V[j]}
if(Debug_P):
print("close_edge = ", close_edge)
vertex_list.append(close_edge)
edge_list.append(temp)
j = j+1
i = i+1
j = 0
if(Debug_P):
print("vertex_list = ", vertex_list)
print("edge_list = ", edge_list)
min_index = list_sort(edge_list)
close_edge = vertex_list[min_index]
U.append(close_edge[‘v‘])
del V[V.index(close_edge[‘v‘])]
if(Debug_P):
print("U=",U)
print("V=",V)
return close_edge
def py_prim(start):
init()
prim_start_vertex(start)
print("init values:")
print("U = ", U)
print("V = ", V)
print("T = ", T)
while(len(U) != V_NUM):
if(Debug_P):
print("len(U) = ", len(U))
our_edge = min_wui()
T.append(our_edge)
print("========RESULT============")
print("U=",U)
print("V=",V)
print("T=",T)
if(__name__ == ‘__main__‘):
Debug_P = 1
py_prim(1)
原文:http://www.cnblogs.com/eternal1025/p/5244587.html