- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL 树
- DSA - 红黑树
- DSA - B 树
- DSA - B+ 树
- DSA - 伸展树
- DSA - Trie 树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen 矩阵乘法
- DSA - Karatsuba 算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim 最小生成树
- DSA - Kruskal 最小生成树
- DSA - Dijkstra 最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最佳合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall 算法
- DSA - 0-1 背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机化算法
- DSA - 随机化算法
- DSA - 随机化快速排序算法
- DSA - Karger 最小割算法
- DSA - Fisher-Yates 洗牌算法
- DSA 有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
Prim 最小生成树
Prim 最小生成树算法是查找图的最小生成树的有效方法之一。最小生成树是一个子图,它以最少的边和最小的成本(分配给每条边的权重的总和)连接主图中存在的所有顶点。
该算法类似于任何最短路径算法,从一个被设置为根的顶点开始,通过确定成本最低的相邻边遍历图中的所有顶点。
Prim 算法
要执行 Prim 算法,算法接收的输入是图 G {V, E},其中 V 是顶点集,E 是边集,以及源顶点 S。图 G 的最小生成树作为输出获得。
算法
声明一个数组 visited[] 用于存储已访问的顶点,首先,将任意根(例如 S)添加到 visited 数组中。
检查最后一个已访问顶点的相邻顶点是否在 visited[] 数组中。
如果顶点不在 visited[] 数组中,则比较边的成本,并将成本最低的边添加到输出生成树中。
将具有最低成本边的相邻未访问顶点添加到 visited[] 数组中,并将最低成本边添加到最小生成树输出中。
步骤 2 和 4 对图中所有未访问的顶点重复执行,以获得给定图的完整最小生成树输出。
计算获得的最小生成树的成本。
示例
使用 Prim 方法(贪心算法)查找下面给定图的最小生成树,其中 S 为任意根。
解决方案
步骤 1
创建一个 visited 数组,将所有已访问的顶点存储到其中。
V = { }
任意根被指定为 S,因此在连接到 S 的所有边中,我们需要找到成本最低的边。
S → B = 8 V = {S, B}
步骤 2
由于 B 是最后一个已访问的顶点,因此检查连接到顶点 B 的成本最低的边。
B → A = 9 B → C = 16 B → E = 14
因此,B → A 是添加到生成树的边。
V = {S, B, A}
步骤 3
由于 A 是最后一个已访问的顶点,因此检查连接到顶点 A 的成本最低的边。
A → C = 22 A → B = 9 A → E = 11
但是 A → B 已经在生成树中了,检查下一个成本最低的边。因此,A → E 被添加到生成树中。
V = {S, B, A, E}
步骤 4
由于 E 是最后一个已访问的顶点,因此检查连接到顶点 E 的成本最低的边。
E → C = 18 E → D = 3
因此,E → D 被添加到生成树中。
V = {S, B, A, E, D}
步骤 5
由于 D 是最后一个已访问的顶点,因此检查连接到顶点 D 的成本最低的边。
D → C = 15 E → D = 3
因此,D → C 被添加到生成树中。
V = {S, B, A, E, D, C}
获得的最小生成树的最小成本 = 46
示例
最终程序实现了 Prim 最小生成树问题,该问题以成本邻接矩阵作为输入,并打印生成树作为输出以及最小成本。
#include<stdio.h> #include<stdlib.h> #define inf 99999 #define MAX 10 int G[MAX][MAX] = { {0, 19, 8}, {21, 0, 13}, {15, 18, 0} }; int S[MAX][MAX], n; int prims(); int main(){ int i, j, cost; n = 3; cost=prims(); printf("Spanning tree:"); for(i=0; i<n; i++) { printf("\n"); for(j=0; j<n; j++) printf("%d\t",S[i][j]); } printf("\nMinimum cost = %d", cost); return 0; } int prims(){ int C[MAX][MAX]; int u, v, min_dist, dist[MAX], from[MAX]; int visited[MAX],ne,i,min_cost,j; //create cost[][] matrix,spanning[][] for(i=0; i<n; i++) for(j=0; j<n; j++) { if(G[i][j]==0) C[i][j]=inf; else C[i][j]=G[i][j]; S[i][j]=0; } //initialise visited[],distance[] and from[] dist[0]=0; visited[0]=1; for(i=1; i<n; i++) { dist[i] = C[0][i]; from[i] = 0; visited[i] = 0; } min_cost = 0; //cost of spanning tree ne = n-1; //no. of edges to be added while(ne > 0) { //find the vertex at minimum distance from the tree min_dist = inf; for(i=1; i<n; i++) if(visited[i] == 0 && dist[i] < min_dist) { v = i; min_dist = dist[i]; } u = from[v]; //insert the edge in spanning tree S[u][v] = dist[v]; S[v][u] = dist[v]; ne--; visited[v]=1; //updated the distance[] array for(i=1; i<n; i++) if(visited[i] == 0 && C[i][v] < dist[i]) { dist[i] = C[i][v]; from[i] = v; } min_cost = min_cost + C[u][v]; } return(min_cost); }
输出
Spanning tree: 0 0 8 0 0 13 8 13 0 Minimum cost = 26
#include<iostream> #define inf 999999 #define MAX 10 using namespace std; int G[MAX][MAX] = { {0, 19, 8}, {21, 0, 13}, {15, 18, 0} }; int S[MAX][MAX], n; int prims(); int main(){ int i, j, cost; n = 3; cost=prims(); cout <<"Spanning tree:"; for(i=0; i<n; i++) { cout << endl; for(j=0; j<n; j++) cout << S[i][j] << " "; } cout << "\nMinimum cost = " << cost; return 0; } int prims(){ int C[MAX][MAX]; int u, v, min_dist, dist[MAX], from[MAX]; int visited[MAX],ne,i,min_cost,j; //create cost matrix and spanning tree for(i=0; i<n; i++) for(j=0; j<n; j++) { if(G[i][j]==0) C[i][j]=inf; else C[i][j]=G[i][j]; S[i][j]=0; } //initialise visited[],distance[] and from[] dist[0]=0; visited[0]=1; for(i=1; i<n; i++) { dist[i] = C[0][i]; from[i] = 0; visited[i] = 0; } min_cost = 0; //cost of spanning tree ne = n-1; //no. of edges to be added while(ne > 0) { //find the vertex at minimum distance from the tree min_dist = inf; for(i=1; i<n; i++) if(visited[i] == 0 && dist[i] < min_dist) { v = i; min_dist = dist[i]; } u = from[v]; //insert the edge in spanning tree S[u][v] = dist[v]; S[v][u] = dist[v]; ne--; visited[v]=1; //updated the distance[] array for(i=1; i<n; i++) if(visited[i] == 0 && C[i][v] < dist[i]) { dist[i] = C[i][v]; from[i] = v; } min_cost = min_cost + C[u][v]; } return(min_cost); }
输出
Spanning tree: 0 0 8 0 0 13 8 13 0 Minimum cost = 26
public class prims { static int inf = 999999; static int MAX = 10; static int G[][] = { {0, 19, 8}, {21, 0, 13}, {15, 18, 0} }; static int S[][] = new int[MAX][MAX]; static int n; public static void main(String args[]) { int i, j, cost; n = 3; cost=prims(); System.out.print("Spanning tree: "); for(i=0; i<n; i++) { System.out.println(); for(j=0; j<n; j++) System.out.print(S[i][j] + " "); } System.out.println("\nMinimum cost = " + cost); } static int prims() { int C[][] = new int[MAX][MAX]; int u, v = 0, min_dist; int dist[] = new int[MAX]; int from[] = new int[MAX]; int visited[] = new int[MAX]; int ne,i,min_cost,j; //create cost matrix and spanning tree for(i=0; i<n; i++) for(j=0; j<n; j++) { if(G[i][j]==0) C[i][j]=inf; else C[i][j]=G[i][j]; S[i][j]=0; } //initialise visited[],distance[] and from[] dist[0]=0; visited[0]=1; for(i=1; i<n; i++) { dist[i] = C[0][i]; from[i] = 0; visited[i] = 0; } min_cost = 0; //cost of spanning tree ne = n-1; //no. of edges to be added while(ne > 0) { //find the vertex at minimum distance from the tree min_dist = inf; for(i=1; i<n; i++) if(visited[i] == 0 && dist[i] < min_dist) { v = i; min_dist = dist[i]; } u = from[v]; //insert the edge in spanning tree S[u][v] = dist[v]; S[v][u] = dist[v]; ne--; visited[v]=1; //updated the distance[] array for(i=1; i<n; i++) if(visited[i] == 0 && C[i][v] < dist[i]) { dist[i] = C[i][v]; from[i] = v; } min_cost = min_cost + C[u][v]; } return(min_cost); } }
输出
Spanning tree: 0 0 8 0 0 13 8 13 0 Minimum cost = 26
inf = 999999 MAX = 10 G = [ [0, 19, 8], [21, 0, 13], [15, 18, 0] ] S = [[0 for _ in range(MAX)] for _ in range(MAX)] n = 3 def main(): global n cost = prims() print("Spanning tree: ") for i in range(n): print() for j in range(n): print(S[i][j], end=" ") print("\nMinimum cost =", cost) def prims(): global n C = [[0 for _ in range(MAX)] for _ in range(MAX)] u, v = 0, 0 min_dist = 0 dist = [0 for _ in range(MAX)] from_ = [0 for _ in range(MAX)] visited = [0 for _ in range(MAX)] ne = 0 min_cost = 0 i = 0 j = 0 for i in range(n): for j in range(n): if G[i][j] == 0: C[i][j] = inf else: C[i][j] = G[i][j] S[i][j] = 0 dist[0] = 0 visited[0] = 1 for i in range(1, n): dist[i] = C[0][i] from_[i] = 0 visited[i] = 0 min_cost = 0 ne = n - 1 while ne > 0: min_dist = inf for i in range(1, n): if visited[i] == 0 and dist[i] < min_dist: v = i min_dist = dist[i] u = from_[v] S[u][v] = dist[v] S[v][u] = dist[v] ne -= 1 visited[v] = 1 for i in range(n): if visited[i] == 0 and C[i][v] < dist[i]: dist[i] = C[i][v] from_[i] = v min_cost += C[u][v] return min_cost #calling the main() method main()
输出
Spanning tree: 0 0 8 0 0 13 8 13 0 Minimum cost = 26