数据结构题:克鲁斯卡尔(Kruscal)算法求最小生成树 您所在的位置:网站首页 数据结构与算法简答题 数据结构题:克鲁斯卡尔(Kruscal)算法求最小生成树

数据结构题:克鲁斯卡尔(Kruscal)算法求最小生成树

2023-11-29 16:00| 来源: 网络整理| 查看: 265

文章目录 前言一、目的与要求设计目的设计要求 二、原理及方案1.克鲁斯卡尔(Kruskal)算法2.方案思路 三、设计过程四、设计结果五、例题测试总结结语

前言

问题描述:用克鲁斯卡尔算法求无向网图的最小生成树。本文编程软件是Visual Studio 2019,使用的是C语言进行课程设计。

提示:以下是本篇文章正文内容,下面案例可供参考。

一、目的与要求 设计目的 该课题的源码必须能够调试成功;提供一个main函数完成的程序源码版本。基本数据结构有详细说明,每个功能函数有详细说明;全文关键代码须加上注释。 设计要求 生成一个无向网图;要求采用邻接矩阵或链接表存储来完成;最后打印输出最小生成树;每一个函数要有必要的注释,在课程设计中有流程图。 二、原理及方案 1.克鲁斯卡尔(Kruskal)算法

克鲁斯卡尔算法的思想是:假设G=(V,E)是一个具有n给顶点的连通网,T=(U,TE)是G的最小生成树。U的初值等于V,即拥有G中的全部顶点。算法开始时,TE的初值为空值。将图G中的边按权值从小到大的顺序依次选取,若选取的边使生成树T不形成回路,则把它并入TE中,保留作为T的一条边;若选取的边使生成树T形成回路,则将其舍弃,如此进行下去,直到TE中包含n-1条边为止,此时的T即为最小生成树。 🎈这里我们通过一个例子了解如何对一个无向带权图采用克鲁斯卡尔算法求其最小生成树:

例,对于下图所示的无向带权图,采用克鲁斯卡尔算法求最小生成树的过程为: 在这里插入图片描述 通过该图,可知其中的边按权值由小到大的顺序是: 从顶点5开始,连接5和4,权值为1 在这里插入图片描述 再连接3,4,权值为2,此时选取的边使生成树T形成回路,舍弃;从另一边连接5,0,权值为3;再连接0,2,权值为4,形成回路舍弃;连接5,1,权值为5,如下图,即得到最小生成树: 在这里插入图片描述

步骤生成树中各顶点集合生成树的边生成树的权值初始状态{0},{1},{2},{3},{4},{5}1{0},{1},{2},{3},{4,5}(4,5)12{0},{1},{2},{3,4,5}(3,4)23{1},{2},{0,3,4,5}(0,5)34{1},{2,0,3,4,5}(0,2)45{1,2,0,3,4,5}(1,5)5

实现该算法需要设一个边集合数组E,其中包括边的起始点u,终止点v和这条边的权值w。首先编写函数CreateEdge循环建立一个边集合E,并返回边的数目n。因为克鲁斯卡尔算法要求边集必须是按从小到大的顺序排好,所以编写函数seeks实现对数组E进行排序的功能,函数sort排序的结果是E中各边按从小到大排好序。 克鲁斯卡尔算法的编程思路是首先要用到辅助数组set,用来存放各顶点所在的最小生成树顶点集合,然后从边集E中顺序取出各条边,判断该边的两个顶点是否在同一集合中(需要编写一个判断顶点所在集合的函数seeks),若不在同一集合,则该边为最小生成树的一条边,输出该条边的顶点序列和权值,并在set数组中将顶点v2加到顶点v1集合中,重复以上操作直到所有顶点都在一个集合中结束。

2.方案思路

Prim算法是找点,而我们所用的Kruscal算法则是从边出发。 具体思路: 1.把所有的边和这条边代表的权值用一个数组存储起来,并按权值大小给数组排序(升序)。 2.按顺序从数组中拿出一条边,检查这条边是否与到目前为止形成的树构成环,如果形成了环,就丢弃它;如果没有,就把这条边加入树中。 3.重复步骤2,直到树中有 n-1 条边为止。

三、设计过程

程序中无向网采用邻接矩阵存储,c程序如下:

//克鲁斯卡尔(Kruscal)算法求最小生成树 #include #define MAX 100 //定义最大顶点数 typedef struct //建立一个边集合数组,其中包括边的起始点、终止点以及这条边的权值 { int u; //一条边的起始顶点 int v; //一条边的终止顶点 int w; //边的权值(权重) }Edge; //边的类型定义 Edge E[MAX]; //定义一个全局数组E,用于存储图的各条边(创建边的数组) //创建一个无向网图 int CreateEdge() { int i; int anum; printf("\n输入无向网的边数:"); scanf_s("%d", &anum); for (i = 0; i int i, j; Edge t; for (i = 0; i int i = v; while (set[i] > 0) i = set[i]; return(i); } //克鲁斯卡尔算法的核心环节 void Kruskal(Edge E[], int n) //算法核心环节 { int set[MAX]; //创建状态临时数组(辅助标志数组) int v1, v2, i; //数组中的下标的临时变量 for (i = 0; i printf("(%d,%d) %d\n",E[i].u,E[i].v,E[i].w); set[v1]=v2; //将v2加入到v1的集合中 } i++; } } void main() { int n; n=CreateEdge(); //调用生成边表函数 if(n>0) //判断输入的n值是否合法(n>0) { sort(n); //对边表集合进行排序 printf("\n最小生成树为( (顶点,顶点) 权值 ):\n"); } else printf("\n输入边数错误,请重新输入!\n"); Kruskal(E,n); //调用克鲁斯卡尔算法求最小生成树 } 四、设计结果

在这里插入图片描述

五、例题测试

刚刚更新,我们通过一道题由以上代码可解决,直接上张图: 在这里插入图片描述 在这里插入图片描述

总结

以上就是今天要讲的内容,本文利用克鲁斯卡尔(Kruscal)算法求最小生成树中(无向网采用邻接矩阵存储),最后我们要知道克鲁斯卡尔算法的时间复杂度是主要由排序方法决定的,其排序方法只与网中边的条数有关,而与网中顶点的个数无关,当使用时间复杂度为O(elog2e)的排序方法时,克鲁斯卡尔算法的时间复杂度即为O(log2e),因此当网的顶点个数较多、而边的条数较少时,使用克鲁斯卡尔算法构造最小生成树效果较好。

结语

本文参考《数据结构》–上海交大 如有错误,欢迎指正! 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有