普里姆和克鲁斯卡尔算法

合集下载

数据结构参考答案

数据结构参考答案

简答一.1、已知模式串pat=’ADABBADADA’,写出该模式串的next函数值和nextval值;2、模式匹配算法是在主串中快速寻找模式的一种有效的方法,如果设主串的长度为m,模式的长度为n,则在主串中寻找模式的KMP算法的时间复杂性是多少?如果,某一模式 P=’abcaacabaca’,请给出它的NEXT函数值及NEXT函数的修正值NEXTVAL之值。

3、已知模式串pat=“abaabc”,写出该模式串的next函数值和nextval值;4、给出字符串‘abacabaaad’在KMP算法中的next和nextval数组。

二、(意思对即可,不一定是这种写法)1、数据结构按照逻辑结构分为哪四种结构,说出元素之间的关系?集合:无关系线性结构:一对一树形结构:一对多图形结构:多对多2、图形结构有几种存储结构?分别是什么存储结构?4种。

邻接矩阵,邻接表,十字链表,邻接多重表3、度数为2的树和二叉树有何区别?(1)度为2的树中至少有一个结点的度为2,而二叉树中没有这种要求。

(2)度为2的树不区分左右子树,而二叉树严格区分左右子树。

4、简述栈和队列的特点。

栈:是一种只能在一端进行插入或删除操作的线性表。

“后进先出”队列:是一种仅允许在表的一端进行插入操作,而在表的另一端进行删除操作的受限的线性表“先进先出”三(只是最终的结果,有的题可能需要中间步骤,自己完善一下)1、已知某有向图的顶点集合为{A,B,C,D,E,F},边集合为{〈A,B〉,〈A,C〉,〈A,E〉,〈C,F〉,〈E,D〉},画出该图的邻接表,以它为基写出深度优先、广度优先遍历序列(深度、广度遍历要求从结点A开始)。

深度:A B C F E D广度:A B C E F D2、设无向图G(如右图所示),给出该图的最小生成树上边的集合并计算最小生成树各边上的权值之和。

3、对下图所示的无向图,从顶点1开始,写出该图的深度优先遍历和广度优先遍历。

作业4图 参考答案

作业4图 参考答案

作业4. 图非编程作业参考答案:1.已知带权无向图如图所示:(1). 根据普里姆(Prim)算法,求它的从顶点a出发的最小生成树(写出过程,即添加顶点、边次序);(2). 根据克鲁斯卡尔(Kruskal)算法,求该图的最小生成树(写出过程,即添加边次序)。

普里姆(Prim)算法:aadaed2aced23acbed1234234克鲁斯卡尔(Kruskal)算法:acbedacbed1acbed12acbed123acbed12342. 已知带权有向图如图所示:(1). 画出该图的邻接矩阵存储结构;(2). 请写出该图的一个拓扑有序序列;(3). 求从顶点a到其余各顶点之间的最短路经及最短路经长度,并给出计算过程。

图G的一个拓扑序列:abdfecgh afbdecghabdfegch afbdegch2421∞∞∞⎢∞∞g02690301050280730∞∞∞∞⎡⎤⎢⎥∞∞∞∞∞⎢⎥⎢⎥∞∞∞∞∞∞⎢⎥∞∞∞∞∞∞⎢⎥⎢⎥∞∞∞∞∞⎢⎥∞∞⎥⎢⎥∞∞∞∞∞⎢⎥∞∞∞∞∞∞⎢⎥⎣⎦a b c d e f g habcdefh从a出发到其它顶点的最短路径及其计算过程:编程作业:请编写一个完整的程序,建立有向图的邻接表存储结构,并判断两顶点间是否有路径存在,要求:(1) 主函数功能:①从键盘读入有向图的顶点数、有向边数,调用函数CreateAdjList()建立邻接表;②在主函数中输出每个顶点的数据域及其所有邻接点;③从键盘读入两个顶点vs 、v t(ts )的数据域,调用函数Path()判断其间是否存在路径;(2) CreateAdjList():建立有向图邻接表。

功能:从键盘接收各顶点数据域及各条有向边所依附的顶点(如:“2,3”代表该边依附的两个顶点在表头数组中的下标为2和3),要求单链表中结点按数据域升序排序;(3) Path(): 判断两顶点间是否存在路径,如果存在,将打印该路径(若存在多条路径,打印其中一条即可)。

最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)

最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)

最⼩⽣成树---普⾥姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)最⼩⽣成树的性质:MST性质(假设N=(V,{E})是⼀个连通⽹,U是顶点集V的⼀个⾮空⼦集,如果(u,v)是⼀条具有最⼩权值的边,其中u属于U,v属于V-U,则必定存在⼀颗包含边(u,v)的最⼩⽣成树)普⾥姆算法(Prim算法)思路:以点为⽬标构建最⼩⽣成树1.将初始点顶点u加⼊U中,初始化集合V-U中各顶点到初始顶点u的权值;2.根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩。

循环n-1次如下操作:(1)从数组lowcost[k]中找到vk到集合U的最⼩权值边,并从数组arjvex[k] = j中找到该边在集合U中的顶点下标(2)打印此边,并将vk加⼊U中。

(3)通过查找邻接矩阵Vk⾏的各个权值,即vk点到V-U中各顶点的权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中以下图为例#include<bits/stdc++.h>using namespace std;#define MAXVEX 100#define INF 65535typedef char VertexType;typedef int EdgeType;typedef struct {VertexType vexs[MAXVEX];EdgeType arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;void CreateMGraph(MGraph *G) {int m, n, w; //vm-vn的权重wscanf("%d %d", &G->numVertexes, &G->numEdges);for(int i = 0; i < G->numVertexes; i++) {getchar();scanf("%c", &G->vexs[i]);}for(int i = 0; i < G->numVertexes; i++) {for(int j = 0; j < G->numVertexes; j++) {if(i == j) G->arc[i][j] = 0;else G->arc[i][j] = INF;}}for(int k = 0; k < G->numEdges; k++) {scanf("%d %d %d", &m, &n, &w);G->arc[m][n] = w;G->arc[n][m] = G->arc[m][n];}}void MiniSpanTree_Prim(MGraph G) {int min, j, k;int arjvex[MAXVEX]; //最⼩边在 U集合中的那个顶点的下标int lowcost[MAXVEX]; // 最⼩边上的权值//初始化,从点 V0开始找最⼩⽣成树Tarjvex[0] = 0; //arjvex[i] = j表⽰ V-U中集合中的 Vi点的最⼩边在U集合中的点为 Vjlowcost[0] = 0; //lowcost[i] = 0表⽰将点Vi纳⼊集合 U ,lowcost[i] = w表⽰ V-U中 Vi点到 U的最⼩权值for(int i = 1; i < G.numVertexes; i++) {lowcost[i] = G.arc[0][i];arjvex[i] = 0;}//根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩for(int i = 1; i < G.numVertexes; i++) {min = INF, j = 1, k = 0;//寻找 V-U到 U的最⼩权值minfor(j; j < G.numVertexes; j++) {// lowcost[j] != 0保证顶点在 V-U中,⽤k记录此时的最⼩权值边在 V-U中顶点的下标if(lowcost[j] != 0 && lowcost[j] < min) {min = lowcost[j];k = j;}}}printf("V[%d]-V[%d] weight = %d\n", arjvex[k], k, min);lowcost[k] = 0; //表⽰将Vk纳⼊ U//查找邻接矩阵Vk⾏的各个权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中for(int i = 1; i < G.numVertexes; i++) {if(lowcost[i] != 0 && G.arc[k][i] < lowcost[i]) {lowcost[i] = G.arc[k][i];arjvex[i] = k;}}}int main() {MGraph *G = (MGraph *)malloc(sizeof(MGraph));CreateMGraph(G);MiniSpanTree_Prim(*G);}/*input:4 5abcd0 1 20 2 20 3 71 2 42 3 8output:V[0]-V[1] weight = 2V[0]-V[2] weight = 2V[0]-V[3] weight = 7最⼩总权值: 11*/时间复杂度O(n^2)克鲁斯卡尔算法(Kruskal算法)思路:以边为⽬标进⾏构建最⼩⽣成树在边集中依次寻找最⼩权值边,若构建是不形成环路(利⽤parent数组记录各点的连通分量),则将其添加到最⼩⽣成树中。

考研数据结构图的必背算法及知识点

考研数据结构图的必背算法及知识点

考研数据结构图的必背算法及知识点Prepared on 22 November 20201.最小生成树:无向连通图的所有生成树中有一棵边的权值总和最小的生成树问题背景:假设要在n个城市之间建立通信联络网,则连通n个城市只需要n—1条线路。

这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。

在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。

n个城市之间,最多可能设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢分析问题(建立模型):可以用连通网来表示n个城市以及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价。

对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。

即无向连通图的生成树不是唯一的。

连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可能得到不同的生成树。

图G5无向连通图的生成树为(a)、(b)和(c)图所示:G5G5的三棵生成树:可以证明,对于有n个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1条边。

最小生成树的定义:如果无向连通图是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树,简称为最小生成树。

最小生成树的性质:假设N=(V,{E})是个连通网,U是顶点集合V的一个非空子集,若(u,v)是个一条具有最小权值(代价)的边,其中,则必存在一棵包含边(u,v)的最小生成树。

解决方案:两种常用的构造最小生成树的算法:普里姆(Prim)和克鲁斯卡尔(Kruskal)。

他们都利用了最小生成树的性质1.普里姆(Prim)算法:有线到点,适合边稠密。

时间复杂度O(N^2)假设G=(V,E)为连通图,其中V为网图中所有顶点的集合,E为网图中所有带权边的集合。

生成树的树形结构

生成树的树形结构

生成树的树形结构生成树是一种用于解决图论问题的重要算法。

它通过选择一些边来连通图中的所有节点,形成一棵树,这棵树称为生成树。

在生成树中,每个节点都能被到达且没有环,它们之间的边权和最小。

生成树算法可以分为两类:普通算法和快速算法。

普通算法比较简单,但是时间复杂度较高,适用于边数比较少的图。

快速算法则通常适用于边数较多的图,能够快速找到最小生成树。

一般地,生成树算法都可以用来解决最小生成树问题,也可以用来解决其他的问题。

下面就介绍一下生成树算法的几个常见应用。

一、最小生成树最小生成树问题是一类十分重要的图论问题。

它的目标是找到一棵包含图中所有节点的树,并且这棵树的边权和最小。

最小生成树问题可以通过生成树算法来解决。

最小生成树算法包括普里姆算法和克鲁斯卡尔算法。

普里姆算法从一个节点开始,逐渐加入节点,形成一棵生成树。

克鲁斯卡尔算法则是选择所有无环的边,形成一棵生成树。

二、连通性问题在某些应用中,需要判断一个图是否连通,即是否存在一条路径可以从图中的任意节点到达任意节点。

对于这类问题,也可以使用生成树算法来解决。

连通性问题的解决方式是构建一棵生成树,如果生成树中包含了所有的节点,则原来的图是连通的。

如果生成树中没有包含所有的节点,则说明原来的图不连通。

三、最短路问题最短路问题是指在一个加权有向图中,寻找一条从起点到终点的路径,使得路径上经过的所有边权值之和最小。

最短路问题可以使用生成树算法来解决。

最短路问题的解决方式是使用迪杰斯特拉算法或贝尔曼-福德算法,构建一棵生成树,找到从起点到终点的最短路径。

总体来看,生成树算法是图论中十分重要的算法之一,不仅包含了最小生成树问题,还可以用来解决连通性问题和最短路问题等多个问题。

克鲁斯卡尔算法和普里姆算法

克鲁斯卡尔算法和普里姆算法

克鲁斯卡尔算法和普里姆算法
克鲁斯卡尔算法和普里姆算法是两种常用的最小生成树算法。

克鲁斯卡尔算法主要思想是:将图中的所有边按照权值从小到大排序,然后依次考虑每条边,如果当前边的两个端点不在同一个连通分量中,则
将当前边加入到最小生成树中。

普里姆算法主要思想是:从一个起点开始,每次选择距离已选定的结
点集合最近的一个结点,并将这个结点加入到已选定的结点集合中。

不断
重复这个过程,直到所有的结点都被加入到最小生成树中。

两种算法的主要区别在于选择下一个结点的方式不同。

克鲁斯卡尔算
法是按照边权值从小到大排序,普里姆算法是按照距离当前结点集合最近
的距离进行选择。

由于每次选择都是最小值,所以普里姆算法更适用于稠
密图,而克鲁斯卡尔算法更适用于稀疏图。

最小生成树问题课程设计

最小生成树问题课程设计

最小生成树问题课程设计一、课程目标知识目标:1. 理解最小生成树的概念,掌握其定义及性质;2. 学会运用普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法求解最小生成树问题;3. 了解最小生成树在实际问题中的应用,如网络设计、电路设计等。

技能目标:1. 能够运用普里姆和克鲁斯卡尔算法解决最小生成树问题,并进行算法分析;2. 能够运用所学知识解决实际问题,具备一定的算法设计能力;3. 能够通过合作与交流,提高问题分析和解决问题的能力。

情感态度价值观目标:1. 培养学生对数据结构与算法的兴趣,激发学习热情;2. 培养学生的团队合作意识,学会倾听、尊重他人意见;3. 培养学生面对问题勇于挑战、积极进取的精神。

课程性质:本课程为计算机科学与技术专业的高年级课程,旨在帮助学生掌握图论中的最小生成树问题及其求解方法。

学生特点:学生具备一定的编程基础和图论知识,对算法有一定的了解,但可能对最小生成树问题尚不熟悉。

教学要求:结合学生特点,采用案例教学、任务驱动等方法,注重理论与实践相结合,培养学生的实际操作能力和创新思维。

通过本课程的学习,使学生能够将所学知识应用于实际问题中,提高解决复杂问题的能力。

二、教学内容1. 最小生成树概念与性质- 定义、性质及定理- 最小生成树的构建方法2. 普里姆算法- 算法原理与步骤- 算法实现与复杂度分析- 举例应用3. 克鲁斯卡尔算法- 算法原理与步骤- 算法实现与复杂度分析- 举例应用4. 最小生成树在实际问题中的应用- 网络设计- 电路设计- 其他领域应用案例5. 算法比较与优化- 普里姆与克鲁斯卡尔算法的比较- 算法优化方法及其适用场景6. 实践环节- 编程实现普里姆和克鲁斯卡尔算法- 分析并解决实际问题- 小组讨论与成果展示教学内容依据课程目标进行选择和组织,注重科学性和系统性。

参考教材相关章节,制定以下教学安排:第1周:最小生成树概念与性质第2周:普里姆算法第3周:克鲁斯卡尔算法第4周:最小生成树在实际问题中的应用第5周:算法比较与优化第6周:实践环节与总结三、教学方法本课程将采用以下多样化的教学方法,以激发学生的学习兴趣和主动性:1. 讲授法:教师通过生动的语言和形象的比喻,对最小生成树的概念、性质、算法原理等基础知识进行讲解,使学生快速掌握课程内容。

普里姆和克鲁斯卡尔算法

普里姆和克鲁斯卡尔算法

前言从学习《数据结构》这门课程开始,我已发现了学习算法的乐趣,在学习这门课的过程中也学到了许多计算机应用基础知识,对计算机的机体也有了一个初步的了解,又在课余时间阅读了大量有关算法设计与分析的图书,在此基础上,利用贪心算法,编写了一个用prim 和kruskal算法求解最小生成树,也以此检验自己一学期所学成果,加深对算法设计与分析这门课程的理解,由于所学知识有限,难免有些繁琐和不完善之处,下面向大家介绍此程序的设计原理,方法,内容及设计的结果。

本程序是在windows 环境下利用Microsoft Visual C++ 6.0所编写的,主要利用贪心算法的思想,以及数组,for语句的循环,if语句的嵌套,运用以上所学知识编写出的prim和kruskal算法求解最小生成树,在输入其边的起始位置,种植位置以及权值后,便可分别输出此网的prim和kruskal算法最小生成树的边的起始位置,终止位置以及权值。

正文2.1 设计方法和内容一.软件环境:Microsoft Visual C++ 6.0二.详细设计思想:所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

贪心算法的基本思路如下:1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每一子问题求解,得到子问题的局部最优解。

4.把子问题的解局部最优解合成原来解问题的一个解。

1.Prim(普里姆)算法思想无向网的最小生成树问题此算法的思想是基于点的贪心,力求从源点到下一个点的距离最短,以此来构建临接矩阵,所以此算法的核心思想是求得源点到下一个点的最短距离,下面具体解释如何求此最短距离:在图中任取一个顶点k作为开始点,令集合U={k},集合w=V-U,其中v为图中所有顶点的集合,然后找出:一个顶点在集合U中,另一个顶点在集合W中的所有边中,权值最短的一条边,,并将该边顶点全部加入集合U中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离,使之保持最小,在重复此过程,直到W为空集为止,求解过程如下:由图可知最小生成树的步骤,假设开始顶点就选为1,故首先有u={1},w={2,3,4,5}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

前言从学习《数据结构》这门课程开始,我已发现了学习算法的乐趣,在学习这门课的过程中也学到了许多计算机应用基础知识,对计算机的机体也有了一个初步的了解,又在课余时间阅读了大量有关算法设计与分析的图书,在此基础上,利用贪心算法,编写了一个用prim 和kruskal算法求解最小生成树,也以此检验自己一学期所学成果,加深对算法设计与分析这门课程的理解,由于所学知识有限,难免有些繁琐和不完善之处,下面向大家介绍此程序的设计原理,方法,内容及设计的结果。

本程序是在windows 环境下利用Microsoft Visual C++ 6.0所编写的,主要利用贪心算法的思想,以及数组,for语句的循环,if语句的嵌套,运用以上所学知识编写出的prim和kruskal算法求解最小生成树,在输入其边的起始位置,种植位置以及权值后,便可分别输出此网的prim和kruskal算法最小生成树的边的起始位置,终止位置以及权值。

正文2.1 设计方法和内容一.软件环境:Microsoft Visual C++ 6.0二.详细设计思想:所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

贪心算法的基本思路如下:1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每一子问题求解,得到子问题的局部最优解。

4.把子问题的解局部最优解合成原来解问题的一个解。

1.Prim(普里姆)算法思想无向网的最小生成树问题此算法的思想是基于点的贪心,力求从源点到下一个点的距离最短,以此来构建临接矩阵,所以此算法的核心思想是求得源点到下一个点的最短距离,下面具体解释如何求此最短距离:在图中任取一个顶点k作为开始点,令集合U={k},集合w=V-U,其中v为图中所有顶点的集合,然后找出:一个顶点在集合U中,另一个顶点在集合W中的所有边中,权值最短的一条边,,并将该边顶点全部加入集合U中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离,使之保持最小,在重复此过程,直到W为空集为止,求解过程如下:由图可知最小生成树的步骤,假设开始顶点就选为1,故首先有u={1},w={2,3,4,5}。

2.kruskal(克鲁斯卡尔)算法的基本思想kruskal(克鲁斯卡尔)算法的基本思想是:将无向图的所有边按权值递增顺序排列,依次选定权值数较小的边,但要求后面选取的边不能与前面选区的边构成回路,若构成回路,则放弃该条边,然后再选后面权值较大的边,n个顶点的图中,选取n-1条边即可。

注意:kruskal算法的贪心是从源点到下一个点的距离最短。

prim算法的贪心是任意点到生成树的距离最短,也就是边的最小。

三,设计方法与内容:1.Prim(普里姆)算法:假设网用邻接矩阵作存储结构,与图的邻接矩阵类似,只是将0变为无穷,1变为对应边上权值,而矩阵中对角线上的元素为0。

(1)定义网中的顶点数,网的边数,这里将网的顶点数定为6个,网的边数定为10个。

(2) 定义一个名为edgeset类,其数据成员fromvex,endvex,weight,分别为一条边的起点,终点和权值。

(3)定义一个名为tree的类,定义了一个最小生成树边集的数组,用数组记录具有最小代价的边,找到后,将该边作为最小生成树的树边保存起来,再定义一个普里姆算法的成员函数prim(tree &t)。

(4)对prim(tree &t)函数进行类外定义,分别将顶点数定义为k,边为m, 权值为w,定义一个变量min,使其等于32767,即无穷大,利用for循环从顶点1出发求最小生成的数边,即设t.ct[i].fromvex=1。

令终止点t.ct[i].endvex=i+1,令t.ct[i].weight=t.s[1][i+1],再利用第二个for循环找到权值最小的树边,从顶点为2开始循环,当j=k-1且小于网中总顶点数时,权值小于无穷则将此权值付给min,并令边m=j。

(5)重新修改树边的距离,将原来的边用权值小的边替换,若当前边k小于n(原定边数),则令tl=t.ct[i].endvex,w=t.s[j][tl],若w<t.ct[i].weight,则令t.ct[i].weight=w,t.ct[i].fromvex=j。

(6)最后利用for循环键入每条边的起始点,终结点及边上的权值。

2.kruskal算法:(1)定义网中的顶点数,网的边数,这里将网的顶点数定为6个,网的边数定为10个。

(2)定义一个名为edgeset2的类,其数据成员fromvex,endvex,weight,分别为一条边的起点,终点和权值。

(3)定义一个名为tree2的类,定义了一个最小生成树边集的数组,用edgesetge2[e+1]存放网中所有的边,定义一个s2[n+1][n+1],s为一个集合,一行元素s[i][0]~s[i][n]表示一个集合,若s[i][t]=1。

则表示顶点t属于该集合,否则不属于该集合,再定义一个普里姆算法的成员函数kruskal(tree2 &t2)。

(4)对kruskal(tree2 &t2)函数进行类外定义,定义k并设初值为1用来统计生成树的边数,定义d并设初值为1用来表示待扫描边的下标位置,定义两个变量m1,m2用来记录一条边的两个顶点所在集合的序号,如果t2.ge2[d].fromvex==j且t2.s2[i][j]==1,则令m1=i,若t2.ge2[d].endvex==j且t2.s2[i][j]==1则令m2=i,最后判断m1是否等于m2,若不等于则令t2.c2[k]=t2.ge2[d],k自加,求出一条边后,合并两个集合,另一个集合设置为空。

(6)最后利用for循环键入每条边的起始点,终结点及边上的权值,要求输入的网中的边上的权值必须为从大到小排列,调用kruskal(t)循环输出一条边的起始点,终结点及边上的权值。

2.3设计流程图图2-22.4 设计结论Prim 算法:在图中任取一个顶点k 作为开始点,令集合U={ k},集合w=V-U,其中v 为图中所有顶点的集合,然后找出:一个顶点在集合U 中,另一个顶点在集合W中的所有边中,权值最短的一条边,,并将该边顶点全部加入集合U中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离,使之保持最小,在重复此过程,直到W为空集为止Kruskal算法:将无向图的所有边按权值递增顺序排列,依次选定权值数较小的边,但要求后面选取的边不能与前面选区的边构成回路,若构成回路,则放弃该条边,然后再选后面权值较大的边,n个顶点的图中,选取n-1条边即可。

其中两个算法的贪心思想有本质的区别:kruskal算法的贪心是从源点到下一个点的距离最短。

而prim算法的贪心是任意点到生成树的距离最短,也就是边的最小。

有关说明(1)程序运行刚开始会出现一个界面:*************请选择一种算法*****************1.prim 算法求解最小生成树2.kruskal 算法求解最小生成树此时便可输入用户想要选择的数值,回车然后进入如(图一或图二)的界面。

(2)接着根据提示输输入一条边的起始点,终结点及边上的权值,如(图三)界面。

(3)重复步骤(2)十次。

(5)即可显示此算法下的最小生成树。

如(图四)界面。

致谢这次课程设计实训老师给我了很大的帮助,让我发现了自身的不足之处,在实际操作过程中犯的一些错误,同时还有有意外的收获。

在具体操作中对这学期所学的数据结构的理论知识得到巩固,达到实训的基本目的,同时也认识到在以后的上机中应更加注意自己曾犯的错误,也发现上机实训的重要作用,特别是对数组和邻接矩阵有了深刻的理解。

通过实际操作,学会数据结构程序编程的基本步骤、基本方法,开发了自己的逻辑思维能力,培养了分析问题、解决问题的能力。

在此感谢学院领导,老师们给我们提供了这样一个良好的平台,让我们学有所用,把我们所学的理论知识与实践结合,锻炼了自己动手操作的能力,希望自己以后有机会多进行这样的实训,培养自身独立思考问题的能力,提高实际操作水平。

参考文献[1] 李根强《C++数据结构》2005年1月第一版中国水利水电出版社[2]侯识忠《数据结构算法程序集》[3] [018602-01/tp] 谭浩强《C程序设计》 2005年7月第三版清华大学出版社 1-378页。

[4]顾仁《高级C++语言程序设计技巧与实例》1995年11月第一版机械工业出版社 1-462页[5] 陈明《数据结构(C++版)》2005年3月第一版清华大学出版社[6] [020923-01/tp] 谭浩强《C++面向对象程序设计》2006年1月第一版清华大学出版社 1-288页[7] 王晓东《数据结构C++语言》2005年7月第一版清华大学出版社附录://*************prim算法*********************#include<iostream.h>const int n=6; //网中顶点数const int e=10; //网中边数class edgeset //定义一条生成树的边的类{public:int fromvex; //边的起点int endvex; //边的终点int weight; //边的权值};class tree{public:int s[n+1][n+1]; //网的邻接矩阵edgeset ct[n+1]; //最小生成树的边集void prim(tree &t); //普里姆算法};void tree::prim(tree &t){int i,j,k,min,tl,m,w; //k为当前顶点数,m为当前边数,w为当前权值for(i=1;i<n;i++) //从顶点1出发求最小生成树的边{t.ct[i].fromvex=1;t.ct[i].endvex=i+1;t.ct[i].weight=t.s[1][i+1];}for(k=2;k<=n;k++){ min=32767;m=k-1;for(j=k-1;j<n;j++) //找权值最小的树边if(t.ct[j].weight<min){ min=t.ct[j].weight;m=j;}edgeset temp=t.ct[k-1];t.ct[k-1]=t.ct[m];t.ct[m]=temp;j=t.ct[k-1].endvex;for(i=k;i<n;i++) //重新修改树边的距离{ tl=t.ct[i].endvex;w=t.s[j][tl];if(w<t.ct[i].weight) //原来的边用权值较小的边取代{t.ct[i].weight=w;t.ct[i].fromvex=j;}}}}//************kruskal算法******************class edgeset2{public:int fromvex;int endvex;int weight;};class tree2 //定义生成树{public:edgeset c2[n]; //存放生成树的边edgeset ge2[e+1]; //存放网中所有边int s2[n+1][n+1]; //s为一个集合,一行元素s[i][0]~s[i][n]表示一个集合 //若s[i][t]=1。

相关文档
最新文档