1. 最小生成树三种方法的代码实现
2.最小生成树-graphics.h动画设计
目录
系列文章目录
前言
一、算法介绍
1.prim算法(1)
2.prim算法(2)
3.Kruskal算法
5、Prim和Kruskal算法比较说明
二、代码讲解
1. 库引入
2. 随机生成矩阵
3. 文件的输出
三、整体代码展示
总结
数据结构最小生成数当中普利姆算法和克鲁斯卡尔算法再加一种普利姆算法的改进,对每一种算法进行了详细的介绍,并比较了三个算法的区别。
因为如果要生成最小生成树的时候,需要知道顶点和边的数据,这就需要不断的调用数据,而如果需要改变顶点数,就需要改文件,比较麻烦,故,此程序采用随机生成矩阵的方式生成最小生成树。
本程序若单单只有表面算法,会呈现出工作量较小的感觉,为了让此次课设有眼前一亮的感觉,所以引用了graphics.h这一库,可以用图的方式呈现出无向网以及不同算法的最小生成树,具体代码在第二篇文章https://blog.csdn.net/m0_53533553/article/details/119538716中详细介绍。
I. 建立一个辅助数组closedge[],先对其进行初始化,让closedge[i]中的vexadj存储第一个出发点的字符(假设为A),lowcost存储邻接矩阵中第一个出发点所在的行的各元素值(出发点到其他各点的权值)。如表1.
Closedeg[i] |
1 |
2 |
3 |
4 |
5 |
6 |
vexadj |
A |
A |
A |
A |
A |
|
lowcost |
0 |
28 |
∞ |
26 |
49 |
∞ |
表1
II. 寻找closedge[]的lowcost中不为0且权值最小的下标k=4,并输出closedge[4]中存的字符到4对应的顶点的字符(A-D),用代码表示为:closedge[k].vexadj—G.vexs[k].
III. 将选过的点的lowcost标记为0。
IV. 再比较邻接矩阵中第k行各点的值与closedeg[i]中lowcost所存储的值,选择权值较小的存储到lowcost当中,并把顶点字符存储到vexadj当中。如表2
Closedeg[i] |
1 |
2 |
3 |
4 |
5 |
6 |
vexadj |
A |
A |
A |
A |
D |
|
lowcost |
0 |
28 |
∞ |
0 |
49 |
91 |
表2
V. 以此类推,重复II、III、IV步骤,直到循环n-1次,则表示n各顶点、n-1条边全部遍历完成,最小生成树创建完成。
I. 将方法1中的辅助结构体换成两个辅助数组start[]和mark[],start[]存储到i点的距离最小的字符的下标,mark[i]标记是否遍历过,遍历过标记为1。假设第一个出发点为A,先初始化start[i]=1,mark[1]=1,其余为0,如表3所示。
i |
1 |
2 |
3 |
4 |
5 |
6 |
Start[i] |
1 |
1 |
1 |
1 |
1 |
1 |
Mark[i] |
1 |
0 |
0 |
0 |
0 |
0 |
G.arcs[start[i]][i].adj |
∞ |
28 |
∞ |
26 |
49 |
∞ |
表3
II. 寻找mark[i]!=1且G.arcs[start[i]][i].adj当中最小的权值的下标k=4,并输出start[4]所对应的顶点字符到4所对应的顶点字符(A-D),用代码表示:G.vexs[start[k]]-G.vexs[k].
III. 将选过的点mark[i]标记为1.
IV. 比较邻接矩阵中第k行各点的值是否比strat[i]行各点的值小,如果小,将strat[i]的值换成k。如表4所示。
i |
1 |
2 |
3 |
4 |
5 |
6 |
Start[i] |
1 |
1 |
1 |
1 |
1 |
4 |
Mark[i] |
1 |
0 |
0 |
1 |
0 |
0 |
G.arcs[start[i]][i].adj |
∞ |
28 |
∞ |
26 |
49 |
91 |
表4
具体代码如下:
for(j=1;j<=G.vexnum;j++){
if(mark[j]!=1){
if(G.arcs[k][j].adj start[j]=k; } } V. 重复II、III、IV的步骤,直到所有的mark[i]的值全为1,表示所有的顶点遍历完成,最小生成树建立完成。 I. 创建辅助结构体数组KEdge h[MAXNUM]以及整形数组fat[]。h[i].a存储第i条最小边的第一个顶点,h[i].b存储第i条最小边的第二个顶点,h[i].w存储第i条边的权值,fat[i]存储与第i个顶点相连的前一顶点(找到这个顶点的树的头结点,防止闭环)。同时设置has变量判断是否所有的顶点都遍历完成。 II. 初始化两个数组,将fat[i]初始化为i,如表6所示。h[i]初始化邻接矩阵中上三角不为无穷的元素的顶点位置和权值。如表6所示。 具体代码如下: for(i=1;i<=G.vexnum;i++){ for(j=i+1;j<=G.vexnum;j++){ if(G.arcs[i][j].adj<=100){ h[k].a=i; //行 h[k].b=j; //列 h[k].w=G.arcs[i][j].adj; k++; } } } i 1 2 3 4 5 6 Fat[i] 1 2 3 4 5 6 表5 a b w H[1] 1 2 28 H[2] 1 4 26 H[3] 1 5 49 H[4] 2 6 9 H[5] 3 5 42 H[6] 2 6 96 H[7] 5 6 81 表6 III. 对h[i]中的w进行升序排序,采用了简单选择排序的方法。 IV. 当has不等于顶点数减一时,利用root函数寻找h[i].a(此时为2)和h[i].b(此时为6)的根结点,根节点寻找思想:当前一节点就是他本身时,则说明是根节点。具体代码如下: int Root(int x,int fat[]){ if(fat[x]!=x) return Root(fat[x],fat); else return x; } 分别赋给x、y,当x!=y时,令fat[y]=x,并输出G.vexs[h[i].a]-G.vexs[h[i].b].此时x=1,y=6,x!=y,令fat[6]=1,并输出A-F.此时fat[i]个数如表7所示。 i 1 2 3 4 5 6 Fat[i] 1 2 3 4 5 1 表7 V. 重复IV的步骤,直到has==顶点个数减一时结束,最小生成树建立完成。 Prim1 closedge[k].vexadj--G.vexs[k] Prim2 G.vexs[start[k]]-G.vexs[k] kruskal G.vexs[h[i].a]-G.vexs[h[i].b] 表8 graphics.txt 该文件为了第二个程序可以画出无向网 输出格式如下: 第一行书写顶点个数 第二行两个为一组,分别书写每个顶点的横纵坐标 第三行三个为一组,分别书写线段从第几个顶点到第几个顶点,以及两顶点之间的权值 tree-1.txt 该文件为了第二个程序可以用普利姆算法画出最小生成树 tree-2.txt 该文件为了第二个程序可以用克鲁斯卡尔算法画出最小生成树 输出格式如下: 两个为一组,分别书写从第几个顶点到第几个顶点 文章核心代码参考https://blog.csdn.net/qq_47733361/article/details/107127316 以上就是最小生成树的具体代码实现,如果不想要图画的生成,只需将文件和主函数中五六七的步骤删除即可,希望能帮助到大家!3.Kruskal算法
5、Prim和Kruskal算法比较说明
二、代码讲解
1. 库引入
#include
2. 随机生成矩阵
/*随机生成图*/
void RandomNumbers(MGraph *G){
int i,j;
srand((unsigned)time(NULL));
for(i=1;i<=G->vexnum;i++){
//对角线为无穷
G->arcs[i][i].adj=INFINITY;
for(j=i+1;j<=G->vexnum;j++){
G->arcs[i][j].adj=rand()%151; //随机生成0-150
G->arcs[j][i]=G->arcs[i][j]; //对称填充
}
}
//对大于100的赋予无穷
for(i=1;i<=G->vexnum;i++){
for(j=i+1;j<=G->vexnum;j++){
if(G->arcs[i][j].adj==0||G->arcs[i][j].adj>100)
G->arcs[i][j].adj=INFINITY;
}
}
}
3. 文件的输出
三、整体代码展示
#include
总结