详细 Prim算法解连通带权图

该博客介绍了使用普里姆算法找出图中最小生成树的过程。通过初始化起点,逐步连接权值最小的边,直至连接所有点,从而构建最小生成树。代码展示了如何在Java中实现这一算法,并给出了一组示例图的连接权重,最后运行了算法并输出了结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

 基本思想:

设该图所有点集为V,V={1,2,3,4,5,6},选择连接起来的点为S,S初始化为S={1},忽略S或V-S内部各点相连情况,专注于S与V-S中的相连情况

①V-S中每个点都确认与S中的点连接的最小权值边,将其存储在closest数组,其权值存储在lowcost数组,初值都为与编号1的连接情况

如 closest[i]=j 表示与i相连的权值最小的边为 j ,lowcost[i]=5表示i相连的最小权值即(i,j)的权

无直接连接就记权值为无穷大

②找到未连接到S的各点最小权值中的最小权值,即lowcost[i]所对应的下标 i 为未连接且lowcost[i]为最小值

③将上述 i 连接到S中,连接对象为S中的 j,因为 closest[i]=j

④V-S中的每个点再判断与 i 的连接权值与已存储的最小权值,看是否需要更新最小权值连接

⑤S==V?终止 : 回到①

package algorism5;

public class Prim {

	public static void prim(int n, float[][] c) {// n为编号1到n个点
		float[] lowcost = new float[n + 1];// lowcost[i]为i与S中邻接点最小的权即c[i][closest[i]]
		int[] closest = new int[n + 1];// closest[i]为i在S中的权最小的邻接顶点,属于S,i属于V-S,
		boolean[] s = new boolean[n + 1];// 表示选择的点,true为选择

		s[1] = true;// 初始值选1
		for (int i = 2; i <= n; i++) {// 每个都初始化
			lowcost[i] = c[1][i];// s中只有1
			closest[i] = 1;// s中只有1一个点,所以其他每个最短邻接点为1
			s[i] = false;// 其他初始化为未选
		}

		for (int i = 1; i < n; i++) {
			float min = Float.MAX_VALUE;// 最大值以免影响最小值判断
			int j = 1;
			for (int k = 2; k <= n; k++) {// 找到已有最小邻接点中权最小的邻接点k,k属于v-s,把k赋给j
				if (lowcost[k] < min && (!s[k])) {
					min = lowcost[k];
					j = k;
				}
			}
			System.out.println(j + "," + closest[j]);// 将上面所得的点与其在s中的最小邻接点连接起来
			s[j] = true;
			for (int k = 2; k <= n; k++) {// j已经被连接,更新v-s中的点有与j连接成新的最小权边
				if ((c[j][k] < lowcost[k]) && (!s[k])) {
					lowcost[k] = c[j][k];
					closest[k] = j;
				}
			}
		}

	}

	public static void main(String args[]) {// 6个点从编号1到6,数组下标0的不用
		float[][] c = new float[7][7];
		for (int i = 0; i < 7; i++)// 设所有点都不连通
			for (int j = 0; j < 7; j++)
				c[i][j] = Float.MAX_VALUE;
		c[1][4] = 5;// 对应点相连
		c[1][2] = 6;
		c[1][3] = 1;
		c[2][3] = 5;
		c[2][5] = 3;
		c[3][4] = 5;
		c[3][5] = 6;
		c[3][6] = 4;
		c[4][6] = 2;
		c[5][6] = 6;
		for (int i = 1; i < 7; i++) {
			for (int j = 1; j <= i; j++) {
				if (j == i) {
					c[i][j] = 0;// 自己到自己
				} else
					c[i][j] = c[j][i];// 无向图对称矩阵
			}
		}
		prim(6, c);
	}
}

结果:

 

### 使用Prim算法构建最小生成树 #### 初始化阶段 对于给定的一个连通无向加图 \(G = (V, E)\),其中\(V\)表示顶点集合,而\(E\)则代表边集。为了初始化Prim算法,选取任意一个起始节点作为根节点,并将其加入到已访问过的节点列表中。 #### 边的选择过程 在每一轮迭代过程中,从未被选中的边集中挑选一条连接已被纳入MST(Minimal Spanning Tree)部分的节点与其他未加入该结构的新节点之间的最短路径上的边[^1]。这条边应当满足两个条件:一是它的一端位于当前形成的MST内;二是另一端处于尚未处理的部分之中。通过这种方式逐步扩展直到所有的顶点都被包含进来为止。 #### 实现细节 下面是一个基于Python实现的简单版本: ```python import sys from collections import defaultdict class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] # A utility function to find the vertex with minimum distance value, # from the set of vertices not yet included in shortest path tree. def minKey(self, key, mstSet): # Initialize min value min_val = sys.maxsize min_index = None for v in range(self.V): if key[v] < min_val and mstSet[v] == False: min_val = key[v] min_index = v return min_index def primMST(self): key = [sys.maxsize] * self.V # Key values used to pick minimum weight edge in cut parent = [None] * self.V # Array to store constructed MST key[0] = 0 # Make key 0 so that this vertex is picked as first vertex mstSet = [False] * self.V # To represent set of vertices not yet included in MST. parent[0] = -1 # First node is always root of MST for cout in range(self.V): # The following loop traverses other V-1 vertices u = self.minKey(key, mstSet) mstSet[u] = True # Add the picked vertex to the MST Set # Update key value and parent index of the adjacent vertices of the picked vertex. for v in range(self.V): # graph[u][v] is non zero only for adjacent vertices of m # mstSet[v] is false for vertices not yet included in MST # Update the key only if graph[u][v] is smaller than key[v] if ((self.graph[u][v] > 0) and mstSet[v] == False and key[v] > self.graph[u][v]): key[v] = self.graph[u][v] parent[v] = u print ("Edge \tWeight") for i in range(1, self.V): print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) ``` 此代码片段展示了如何利用邻接矩阵来存储图的信息并执行Prim算法以找到最小生成树。每次循环都会选出一个新的节点及其对应的最优边加入到正在增长的MST中去[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值