普里姆算法(Prim)求最小生成树

  • 算法设计
  1. 任选图中一个顶点加入U1
  2. 选取U1中点与U2中点连接成的最小的邻边,将该边原来在U2中的那个顶点加入U1,将此边加入 最小生成树中
  3. 重复步骤2直到边数等于顶点数减一
  • 算法图解:

  • 代码(邻接矩阵)
//普利姆算法:将图的所有顶点分成两个顶点集,一个存放树的结点,另一个存放未在生成树中的点
//每次找已经是树节点的最小边,因为它是运用了切分定理所以不会形成回路不用判断
/*
 * 类描述:普利姆算法求最小生成树
 *@author @Lqx
 */
public class Prim {
	public static final int M = -1;
	// 存储图的邻接矩阵
	static int[][] map= { 
			{ M, 9, M, M, 16, 2 }, 
			{ 9, M, 14, M, M, 2 }, 
			{ M, 14, M, 7, M, 21 },
			{ M,  M, 7, M, 5, 3 },
			{ 16, M, M, 5, M, 7 }, 
			{ 2, 2, 21, 3, 7, M } 
			};
//	boolean visited[] = new boolean[map.length];
	// 存放树中的点,初始化为false,false的所有点为不在生成树中的结点的一个点集,true的所有点为在生成树中结点的点集
	static boolean[] add = new boolean[map.length]; 
	static int[][] edge = new int[map.length][map.length]; //存放树枝
	static int[][] prim(int[][] a, int origin) {

		int vexnumber = a.length;
		for (int i = 0; i < vexnumber; i++) {
			add[i] = false;
		}
		add[origin] = true; // 第一个点加入
		int begin=0; //存放起点下标
		int tempmin = -1;
		int end = -1;
		int number = 0;
		while (number != vexnumber - 1) {
			// 只要边数等于顶点数-1就结束
			for (int i = 0; i < vexnumber; i++) {
				if (add[i]) {
					// 如果在树节点集中,就找与它相邻的最小边,这里因为对每个在树中的顶点进行标记,所以不会将自环加入树中
					for (int j = 0; j < vexnumber; j++) {
						if (a[i][j] != M && add[j]==false) {
							//必须是存在通路,并且该点还不在生成树中
							if (tempmin == -1 || a[i][j] < tempmin) {
								// 找最小边
								tempmin = a[i][j]; // 暂时存放最小边
								begin=i;
								end = j;
							}
						}
					}
				}
				
			}
			edge[begin][end] = tempmin; // 加入边集
			a[begin][end] = -1; // 让原本的边无效
			add[end] = true; // 把该点加入点集中
			tempmin=-1; //重新让它恢复原值不然会导致后面出错
			number++; //计算树枝的数量(边数)
		}
		return edge;
	}

	public static void main(String[] args) {
		int[][] b = prim(map, 0);
		System.out.println("该图的最小生成树结点和树枝情况如下:");
		for (int i = 0; i < b.length; i++) {
			for (int j = 0; j < b.length; j++) {
				if (b[i][j] != 0) {
					System.out.println( "v"+(i+1) + "-->v"+(j+1) + ": " + b[i][j] + "(权值)");
				}
			}
		}
	}
}
  •  结果(输出结果并不是按照生成过程的顺序输出而是按照二维数组遍历顺序):

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
普里姆算法是一种用于解加权无向连通图的最小生成树的算法。其基本思想是从一个顶点开始,每次选择一个与当前生成树相邻的权值最小的顶点加入生成树中,直到所有顶点都被加入为止。具体步骤如下: 1. 任选一个顶点作为起始点,将其加入生成树中。 2. 找到与当前生成树相邻的所有顶点,并计算它们与当前生成树的距离(即边的权值)。 3. 选择距离最小的顶点,将其加入生成树中。 4. 重复步骤2和3,直到所有顶点都被加入为止。 下面是一个Python实现的例子: ```python def prim(graph): # 初始化生成树和已经加入生成树的顶点集合 mst = [] visited = set() # 任选一个顶点作为起始点 start = list(graph.keys())[0] visited.add(start) while len(visited) < len(graph): # 找到与当前生成树相邻的所有顶点,并计算它们与当前生成树的距离 candidates = [] for v in visited: for w, weight in graph[v].items(): if w not in visited: candidates.append((v, w, weight)) # 选择距离最小的顶点,将其加入生成树中 edge = min(candidates, key=lambda x: x[2]) mst.append(edge) visited.add(edge[1]) return mst ``` 其中,`graph`是一个字典,表示无向图的邻接表。字典的键是顶点,值是一个字典,表示与该顶点相邻的顶点及其边的权值。例如,对于下面这个无向图: ``` 2 / \ 1 3 \ / 4 ``` 其邻接表可以表示为: ```python graph = { 1: {2: 2, 4: 1}, 2: {1: 2, 3: 3}, 3: {2: 3, 4: 4}, 4: {1: 1, 3: 4} } ``` 调用`prim(graph)`函数即可出该图的最小生成树

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值