普里姆算法(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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值