目录
适用条件
测试所用图
算法详解
Prim算法代码
全部代码
实验结果
适用条件
加权连通图
测试所用图
所用原图及生成过程
其中,(a) 为原图,圆圈里面是节点的名称,边上的数字是边的权值。由实线连接的点就是集合U,即生成树在生成过程中加入的点。由虚线连接的点中不包含在集合U中的就是集合V-U,即待加入到生成树的点。虚线的变化就是在每次有节点加入集合U时,V-U中的点更新到集合U的最小权值,也是贪心算法的精髓之处。
算法详解
Prim算法又称为加边法,即每次选择最小权值的边加入到生成树中,然后再更新权值,如此反复,保证每次最优来达到最优解。
所用数据结构
typedef struct closedge
{
int adjvex; //最小边在集合U(最小边在当前子树顶点集合中的那个顶点的下标)
int lowcost; //最小边上的权值
};
注:算法中所提到的集合U与集合V-U,可以通过lowcost是否为0进行区分,没必要浪费空间。
初始化
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
0 |
0 |
0 |
0 |
0 |
lowcost |
0 |
6 |
1 |
5 |
∞ |
∞ |
集合U |
0 |
添加第一条边
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
2 |
2 |
0 |
2 |
2 |
lowcost |
0 |
5 |
0 |
5 |
6 |
4 |
集合U |
0,2 |
可以看到,初始化后,顶点2与集合U(顶点0)之间的距离是最小的。所以,添加顶点2至集合U;接下来进行更新,发现原节点1与集合U(顶点0)之间的距离6>现在节点1与集合U(顶点0、2)之间的距离5,所以进行更新。将adjvex更新为节点1与集合U最小距离时的集合U中顶点,lowcost就是选择的边的权值。
以上的话请读者再仔细阅读一遍,并结合测试所用图来考虑标红的其他部分。下面的表不再赘述。
添加第二条边
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
2 |
2 |
5 |
2 |
5 |
lowcost |
0 |
5 |
0 |
2 |
6 |
0 |
集合U |
0,2,5 |
添加第三条边
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
2 |
2 |
3 |
2 |
5 |
lowcost |
0 |
5 |
0 |
0 |
6 |
0 |
集合U |
0,2,5,3 |
添加第四条边
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
1 |
2 |
3 |
1 |
5 |
lowcost |
0 |
0 |
0 |
0 |
3 |
0 |
集合U |
0,2,3,5,1 |
添加第五条边
顶点数组下标i |
0 |
1 |
2 |
3 |
4 |
5 |
adjvex |
0 |
1 |
2 |
3 |
4 |
5 |
lowcost |
0 |
0 |
0 |
0 |
0 |
0 |
集合U |
0,2,3,5,1,4 |
Prim算法代码
//最小生成树-Prim算法 参数:图G
void Prim(Graph G)
{
int v=0;//初始节点
closedge C[MaxVerNum];
int mincost = 0; //记录最小生成树的各边权值之和
//初始化
for (int i = 0; i < G.vexnum; i++)
{
C[i].adjvex = v;
C[i].lowcost = G.Edge[v][i];
}
cout << "最小生成树的所有边:"<< endl;
//初始化完毕,开始G.vexnum-1次循环
for (int i = 1; i < G.vexnum; i++)
{
int k;
int min = INF;
//求出与集合U权值最小的点 权值为0的代表在集合U中
for (int j = 0; j
全部代码
/*
Project: 图-最小生成树-Prim算法
Date: 2019/11/10
Author: Frank Yu
基本操作函数:
InitGraph(Graph &G) 初始化函数 参数:图G 作用:初始化图的顶点表,邻接矩阵等
InsertNode(Graph &G,VexType v) 插入点函数 参数:图G,顶点v 作用:在图G中插入顶点v,即改变顶点表
InsertEdge(Graph &G,VexType v,VexType w) 插入边函数 参数:图G,某边两端点v和w 作用:在图G两点v,w之间加入边,即改变邻接矩阵
Adjancent(Graph G,VexType v,VexType w) 判断是否存在边(v,w)函数 参数:图G,某边两端点v和w 作用:判断是否存在边(v,w)
BFS(Graph G, int start) 广度遍历函数 参数:图G,开始结点下标start 作用:宽度遍历
DFS(Graph G, int start) 深度遍历函数(递归形式)参数:图G,开始结点下标start 作用:深度遍历
Dijkstra(Graph G, int v) 最短路径 - Dijkstra算法 参数:图G、源点v
功能实现函数:
CreateGraph(Graph &G) 创建图功能实现函数 参数:图G InsertNode 作用:创建图
BFSTraverse(Graph G) 广度遍历功能实现函数 参数:图G 作用:宽度遍历
DFSTraverse(Graph G) 深度遍历功能实现函数 参数:图G 作用:深度遍历
Shortest_Dijkstra(Graph &G) 调用最短路径-Dijkstra算法 参数:图G、源点v
Prim(Graph G) 最小生成树-Prim算法 参数:图G
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
实验结果
实验结果截图
与kruskal算法的对比在这篇文章中:最小生成树-Kruskal算法详解(含全部代码)
更多数据结构与算法实现:数据结构(严蔚敏版)与算法的实现(含全部代码)
有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。