Prim(普里姆)算法求最小生成树(邻接矩阵)

在这里插入图片描述

一、项目功能、方案选择及性能描述:

功能:
1.列出目标系统具有的各个功能,并简述其作用
建立无向图:
输入点的数目和标识、边的数目及其权值,使用二维数组的方式建立无向图并用邻接矩阵的方式进行存储。

找出最小生成树:
从输入的起始点开始,使用Prim算法来寻找最小生成树,并输出树的结点和边。

构造辅助数组:
设置一个一维数组每寻找一个顶点,清空一次,得到最小权值的顶点下标。

画出连通图:
使用EasyX画出之前输入的无向图及标记边的权值。

演示Prim算法:
逐步演示Prim算法的寻找过程,并把得到的最小生成树用蓝色进行标记,辅以文字说明。

画出最小生成树:
对最小生成树进行重构得到MST。

2.列出目标系统计划完成的界面样式及操作
方案选择:
1、完成目标系统计划采用数据结构的逻辑结构;
数据结构:无向图——使用邻接矩阵来存储无向图。
逻辑结构:图形结构——因为图形结构的元素之间的关系是邻接的。

2、完成目标系统计划采用的存储结构。
存储结构:顺序存储结构——使用二维数组来存储邻接矩阵。
在这里插入图片描述
性能:
1、说明目标系统的数据处理能力。
一次只能处理一个无向图,无向图使用邻接矩阵来存储,用二维数组来实现,即无向图的顶点数目不超过10000。

2、说明目标系统的时间特性。
使用Prim算法在邻接矩阵中求最小生成树,设顶点数为n,时间复杂度为O(n²)。
响应时间:小于1ms;
更新处理时间:大约1μs;
数据的转换和传送时间:小于1μs;
运行时间:大约1μs。
在这里插入图片描述

二、主要开发思路、工作重点及技术路线

主要开发思路:
将项目分为三大模块:无向图模块、Prim算法模块、演示动画模块。

(1)无向图模块:
通过顶点的个数和边及其权值,使用二维数组来构造邻接矩阵,使用邻接矩阵来存储无向图,包括了顶点和边的信息的输入。

(2)Prim算法模块:
通过无向图模块得到一个邻接矩阵,使用Prim算法在邻接矩阵中找到最小生产数,并输出数的边及其两个端点,为动画演示求得结果。

(3)动画演示模块:
由邻接矩阵来画出无向图,通过Prim算法的每一步求得符合条件的顶点及边,并将其输出在画面,一步一步直到寻找到整颗完整的最小生成树。

工作重点:
Prim算法:单独使用一个数组,来存储最小权值边的顶点,来一步步求出最小生成树。
动画演示:在无向图中,根据Prim算法来一步步演示求得的顶点和边,最后得到最小生成树。

技术路线:如采用C/S模式,使用C++语言编程实现。主要涉及的技术有:MFC中各种控件,图形绘制,窗口拆分,自定义消息,线程同步,数据共享锁等。

使用C++语言编程实现。
主要涉及的技术有:EasyX的图片读取、窗口定义、图形绘制等;多函数的互相调用,宏定义等。

开发环境及工具:
系统核心算法采用Visual Studio开发平台,界面采用EasyX来进行动画演示。

三、软件结构设计

1、软件功能结构
系统功能结构图
2、功能模块说明
2.1 构造无向图
模块全名:void CreateUDN(MGraph *G);
初始条件:MGraph、ArcCell两个结构体为空,无向图的大小未定义。
过程:输入点的数目和标识、边的数目及其权值,使用二维数组的方式建立无向图并用邻接矩阵的方式进行存储。
操作结果:定义无向图的顶点数和边数,并用邻接矩阵存储了无向图的顶点及其边的权值。

2.2 构造辅助数组:
模块全名:int minimun(MGraph G, closedge close);
初始条件:closedge a_close为空
过程:设置一个一维数组每寻找一个顶点,清空一次,得到最小权值的顶点下标。
操作结果: closedge a_close每寻找一个顶点,清空一次,得到最小权值的顶点下标

2.3 PRIM算法求最小生成树:
模块全名:void miniSpanTreePrim(MGraph G, VertexType u);
初始条件:已知起始顶点的下标,closedge a_close为空。
过程:从输入的起始点开始,使用Prim算法来寻找最小生成树,并输出树的结点和边。
操作结果:每一次得到一个最小权值边的终止顶点的下标。

2.4 画出连通图:
模块全名:void cartoon_DRAW();
初始条件:画布为空,背景为白,画线颜色为黑色。
过程:使用EasyX画出之前输入的无向图及标记边的权值。
操作结果:画出之前输入的无向图及标记边的权值。

2.5演示PRIM算法:
模块全名:void cartoon_TEXT();
初始条件:背景为白,画线颜色为蓝色,画布有无向图一个。
过程:逐步演示Prim算法的寻找过程,并把得到的最小生成树用蓝色进行标记,辅以文字说明。
操作结果:逐步演示Prim算法的寻找过程,并把得到的最小生成树用蓝色进行标记,辅以文字说明。

2.6画出最小生成树:
模块全名:void cartoon_MST();
初始条件:得到了无向图及其最小生成树权值的边和过程的文字说明。
过程:对最小生成树进行重构得到MST。
操作结果:对最小生成树进行重构得到MST。

四、数据结构设计

1、构造无向图:
数组:使用二维数组可以存储邻接矩阵,无向图可以用邻接矩阵表示,且邻接矩阵在Prim算法中寻找更加方便,可以节约空间。
定义:

typedef struct {
   
ARCType adj;                            //对于无权图,用 1 或 0 表示是否相邻;对于带权图,直接为权值
}ArcCell, AdjMatrix[MAX_SIZE][MAX_SIZE];
typedef struct {
   
	VertexType vexs[MAX_SIZE];				//存储图中顶点数据
	AdjMatrix arcs;                         //二维数组,记录顶点之间的关系
	int vexnum, arcnum;                     //记录图的顶点数和边数
}MGraph;

2、构造辅助数组:
数组:使用一维数组来存储寻找的顶点的边,使用遍历寻找出权值最小的边,对应的下一个顶点。
定义:

typedef struct {
   
	VertexType adjvex;						//记录权值最小的边的起始点
	ARCType lowcost;						//记录该边的权值
}closedge[MAX_SIZE];

3、PrIM算法求最小生成树:
数组:利用邻接矩阵和辅助数组来求得最小生成树,从起始点开始,寻找出权值最小的边及其及其对应的点,再寻找下一个顶点

五、关键算法设计

1、PRIM算法求最小生成树算法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 32
    点赞
  • 197
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
创建图邻接矩阵的步骤如下: 1. 定义一个二维数组来表示图的邻接矩阵,其中第i行第j列的值表示节点i到节点j的边权重。如果两个节点之间没有边,则该位置的值可以设置为无穷大或者一个非常大的值。 2. 初始化邻接矩阵,将所有值都设为无穷大或者一个非常大的值。 3. 遍历所有的边,将相应位置的值设置为边的权重。 下面是一个简单的示例代码: ```c #include <stdio.h> #define MAX 100 #define INF 0x7fffffff int G[MAX][MAX]; int n, m; void createGraph() { int i, j, u, v, w; scanf("%d %d", &n, &m); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { G[i][j] = INF; } } for(i = 1; i <= m; i++) { scanf("%d %d %d", &u, &v, &w); G[u][v] = G[v][u] = w; } } ``` 接下来,我们使用普里算法最小生成普里算法是一种贪心算法,它的基本思想是从一个任意节点开始,不断选择与当前生成相连的最小边,直到所有的节点都被连通为止。具体步骤如下: 1. 选择一个任意节点作为起点,加入生成中。 2. 遍历与生成相邻的节点,找到其中权重最小的一条边,将它所连接的节点加入生成中。 3. 重复步骤2,直到所有的节点都被加入生成中。 下面是一个简单的示例代码: ```c void prim() { int i, j, k, min, sum = 0; int lowcost[MAX], closest[MAX]; for(i = 2; i <= n; i++) { lowcost[i] = G[1][i]; closest[i] = 1; } closest[1] = 0; for(i = 2; i <= n; i++) { min = INF; k = 0; for(j = 2; j <= n; j++) { if(closest[j] != 0 && lowcost[j] < min) { min = lowcost[j]; k = j; } } closest[k] = 0; sum += min; for(j = 2; j <= n; j++) { if(closest[j] != 0 && G[k][j] < lowcost[j]) { lowcost[j] = G[k][j]; closest[j] = k; } } } printf("最小生成的权值之和为:%d\n", sum); } ``` 在上面的代码中,我们使用两个数组`lowcost`和`closest`来记录生成中与每个节点相连的最小边和最近的节点。在初始化时,我们将数组`lowcost`和`closest`分别设置为节点1到其他节点的边权重和节点1。接着,我们遍历所有的节点,找到与当前生成相邻的节点中,权重最小的一条边,并将它所连接的节点加入生成中。接着,我们更新数组`lowcost`和`closest`中的值,继续遍历下一个节点,直到所有的节点都被加入生成中。 完整代码如下: ```c #include <stdio.h> #define MAX 100 #define INF 0x7fffffff int G[MAX][MAX]; int n, m; void createGraph() { int i, j, u, v, w; scanf("%d %d", &n, &m); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { G[i][j] = INF; } } for(i = 1; i <= m; i++) { scanf("%d %d %d", &u, &v, &w); G[u][v] = G[v][u] = w; } } void prim() { int i, j, k, min, sum = 0; int lowcost[MAX], closest[MAX]; for(i = 2; i <= n; i++) { lowcost[i] = G[1][i]; closest[i] = 1; } closest[1] = 0; for(i = 2; i <= n; i++) { min = INF; k = 0; for(j = 2; j <= n; j++) { if(closest[j] != 0 && lowcost[j] < min) { min = lowcost[j]; k = j; } } closest[k] = 0; sum += min; for(j = 2; j <= n; j++) { if(closest[j] != 0 && G[k][j] < lowcost[j]) { lowcost[j] = G[k][j]; closest[j] = k; } } } printf("最小生成的权值之和为:%d\n", sum); } int main() { createGraph(); prim(); return 0; } ``` 注意,上面的代码中使用了无穷大来表示两个节点之间没有边。在实际使用时,可以根据具体情况选择一个合适的值来表示无穷大。此外,普里算法的时间复杂度为O(n^2),其中n为节点数。当节点数比较大时,可能需要使用更高效的算法解最小生成

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值