普里姆算法

普利姆算法(Prim):
图论中的一种算法,用来在加权连通图中构造最小代价生成树,何为最小代价生成树呢,也就是通过此算法生成的树,不但包括了原连通图中的所有节点,而且保证了所有边的权值之和最小。

算法原理:
现有一个加权联通图,顶点集合为V,边的集合为E,构造最小代价生成树时,Vnew代表生成树的顶点集合,Enew代表生成树的边的集合,最小代价生成树的过程如下:
1.初始化,Vnew = {V0},Enew = {},即选择从顶点V0开始构造最小代价生成树(也可以选择其他任意的顶点)
2.在集合E中选取权值最小的边<u,v>,其中u为集合Vnew中的元素,但是v不是集合Vnew中的元素,将这个顶点v和边分别添加到Vnew和Enew中
重复步骤2,直到V = Vnew,也就是最小代价生成树中的顶点和原图中的顶点完全一样时,算法结束
prim
实现代码如下:

//int[][] G就是传入的图
//G[i][j]表示顶点i和顶点j之间相连边的权值,如果G[i][j] = 0,表示顶点ij不相邻
public void prim(int[][] G){
	//这是数组用来保存每个顶点是否被遍历过
	boolean[] isMark = new boolean[G.length];
	//用来保存已经遍历过的顶点
	ArrayList<Integer> result = new ArrayList<>();
	//初始随意选择一个顶点作为起始点,这里选择顶点0
	result.add(0);
	isMark[0] = true;
	while(result.size()<G.length){
		//distance用来寻找最小权值
		int distance = Integer.MAX_VALUE;
		//u表示已遍历顶点中和未遍历顶点有最小权值的一个已经在Vnew中的顶点
		int u = -1;
		//u表示未遍历顶点中和以遍历顶点有最小权值的一个未在Vnew中的顶点
		int v = -1;
		for(int i = 0;i<result.size();i++){
			int minu = result.get(i);
			for(int j=0;j<G.length;j++){
				//当前顶点未被遍历,而且顶点minu和顶点j联通,
				//而且他们之间边的权值小于之前的最小权值时,对distance,u,v进行更新
				if(!isMark[j]){
					if(G[minu][j]!=0&&G[minu][j]<distance){
						distance = G[minu][j];
						u = minu;
						v = j;
					}
				}
			}
		}
		//将新的顶点加入到result中,最后result中存放的是按顺序加入最小代价生成树中的每一个顶点
		isMark[v] = true;
		result.add(v);
	}
}

prim算法在边数较多的图中有着更高的效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
普里姆算法和克鲁斯卡尔算法都是求解最小生成树的经典算法普里姆算法的基本思想是从一个点开始,每次选择一个与当前生成树距离最近的点加入生成树中,直到所有点都被加入生成树为止。具体实现时,可以使用一个优先队列来维护当前生成树与未加入生成树的点之间的距离,每次从队列中取出距离最小的点加入生成树中,并更新队列中其他点的距离。 以下是普里姆算法的Python实现: ```python import heapq def prim(graph): n = len(graph) visited = [False] * n dist = [float('inf')] * n dist[0] = 0 pq = [(0, 0)] mst = [] while pq: d, u = heapq.heappop(pq) if visited[u]: continue visited[u] = True mst.append(u) for v, w in graph[u]: if not visited[v] and w < dist[v]: dist[v] = w heapq.heappush(pq, (w, v)) return mst ``` 克鲁斯卡尔算法的基本思想是从所有边中选择权值最小的边加入生成树中,直到生成树中包含所有点为止。具体实现时,可以使用并查集来维护当前生成树中的连通性,每次从所有边中选择权值最小的边,如果这条边连接的两个点不在同一个连通块中,则将这条边加入生成树中。 以下是克鲁斯卡尔算法的Python实现: ```python def kruskal(graph): n = len(graph) parent = list(range(n)) rank = [0] * n edges = [] for u in range(n): for v, w in graph[u]: edges.append((w, u, v)) edges.sort() mst = [] for w, u, v in edges: pu, pv = find(parent, u), find(parent, v) if pu != pv: mst.append((u, v, w)) union(parent, rank, pu, pv) return mst def find(parent, u): if parent[u] != u: parent[u] = find(parent, parent[u]) return parent[u] def union(parent, rank, pu, pv): if rank[pu] > rank[pv]: parent[pv] = pu elif rank[pu] < rank[pv]: parent[pu] = pv else: parent[pu] = pv rank[pv] += 1 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值