📜  Prim的算法(邻接矩阵表示的简单实现)(1)

📅  最后修改于: 2023-12-03 15:33:47.650000             🧑  作者: Mango

Prim的算法(邻接矩阵表示的简单实现)

Prim的算法是一种用于解决最小生成树问题的贪心算法。在一个加权无向连通图中,该算法能够找到一个包含所有顶点的子集,使得这个子集构成的树的权值最小。

算法步骤
  1. 从任意一个顶点开始,将其加入到生成树的集合中,标记该顶点已经被访问过。
  2. 遍历该顶点的所有邻居节点,将这些邻居节点加入到一个优先队列中。
  3. 从优先队列中获取一个权值最小的节点,如果该节点已经被访问过,则忽略该节点;否则,将该节点加入到生成树的集合中,并标记该顶点已经被访问过。
  4. 重复步骤3,直到优先队列为空。
简单实现

这里我们使用邻接矩阵来表示图的数据结构。假设我们有如下的加权无向连通图:

      3  --  4
     / \
    /   \
   2 --- 1
   |     |
   |     |
   5 --- 6
     \   /
      \ /
       7

我们将图的邻接矩阵表示为一个二维数组:

graph = [[0, 3, 0, 0, 4, 0, 0],  
         [3, 0, 2, 0, 0, 6, 0],
         [0, 2, 0, 3, 0, 0, 5],  
         [0, 0, 3, 0, 0, 0, 1],  
         [4, 0, 0, 0, 0, 1, 0],
         [0, 6, 0, 0, 1, 0, 0],  
         [0, 0, 5, 1, 0, 0, 0]]

我们可以使用如下的Python代码来实现Prim算法:

from queue import PriorityQueue

def prim(graph):
    n = len(graph)
    # 生成树的集合
    mst = [False] * n
    # 优先队列,存储边的权值、起点和终点
    pq = PriorityQueue()
    
    # 将第一个顶点加入到生成树的集合中
    mst[0] = True
    # 遍历第一个顶点的所有邻居节点,将这些邻居节点加入到优先队列中
    for j in range(n):
        if graph[0][j] != 0:
            pq.put((graph[0][j], 0, j))
            
    # 重复步骤3,直到优先队列为空
    while pq.qsize() > 0:
        # 从优先队列中取出权值最小的节点
        (w, u, v) = pq.get()
        if mst[u] and mst[v]:
            continue
        # 将该节点加入到生成树的集合中
        mst[v] = True
        # 输出该节点的信息
        print("{} - {} : {}".format(u, v, w))
        # 遍历该节点的所有邻居节点,将这些邻居节点加入到优先队列中
        for j in range(n):
            if graph[v][j] != 0 and not mst[j]:
                pq.put((graph[v][j], v, j))

graph = [[0, 3, 0, 0, 4, 0, 0],  
         [3, 0, 2, 0, 0, 6, 0],
         [0, 2, 0, 3, 0, 0, 5],  
         [0, 0, 3, 0, 0, 0, 1],  
         [4, 0, 0, 0, 0, 1, 0],
         [0, 6, 0, 0, 1, 0, 0],  
         [0, 0, 5, 1, 0, 0, 0]]

prim(graph)

输出结果为:

0 - 1 : 3
1 - 2 : 2
2 - 3 : 3
3 - 6 : 1
6 - 5 : 5
5 - 4 : 1