/*******************************最小代价生成树之普利姆算法思想:-----------贪心算法思想从图中任意取出一个顶点,把它当成一棵树,然后从与这棵树相邻接的边中选取一条最短(权值最小)的边,并将这条边及其所连接的顶点也并入这棵树中,此时得到了一颗有两个顶点的树。然后从于这棵树相邻接的边中选取一条最短的边,并将这条边及其所连接的顶点并入当前树中,得到一棵有三个顶点的树。以此类推,直到图中所有顶点都被并入树中为止,此时得到的生成树就是最小生成树。普利姆算法执行过程:从树中某个顶点V0开始,构造生成树的算法过程如下:1、将v0到其他顶点的所有边当做侯选边;2、重复以下步骤n-1次,使得其他n-1个顶点被并入生成树中。1)从侯选边中挑选出权值最小的边输出,并将于该边另一端相连接的顶点v并入生成树中2)考察所有剩余顶点vi,如果(vi,vj)的权值比lowcost[vi]小,则用(vi,vj)的权值更新lowcost[vj]********************************///普利姆算法的代码:struct MGraph{int n; // 顶点总数int edges[MAXSIZE][MAXSIZE];  // 边的权值};void Prim(MGraph& g,int v0,int sum)
{int lowcost[MAXSIZE], vset[MAXSIZE], v;int i = 0, j = 0, k = 0, mincost = 0;v = v0;for (i = 0; i < g.n; ++i){lowcost[i] = g.edges[v0][i];vset[i] = 0;}vset[v0] = 1;     // 将v0并入树中sum = 0;          // sum清零用来记录树的权值for (i = 0; i < g.n -1; ++i){mincost = lowcost[i];for (j = 0; j < g.n; ++j){if (vset[j] == 0 && lowcost[j] < mincost)   // 选出当前生成树中到其余顶点最短边中的最短的一条{mincost = lowcost[j];k = j;}vset[k] = 1;v = k;sum += mincost;  //此处记录了最小生成树的权值}//以刚并入的顶点v为媒介选取新的侯选边for (j = 0; j < g.n; ++j)  // 执行过程中的第二步{if (vset[j] == 0 && g.edges[v][j] < lowcost[j]){lowcost[j] = g.edges[v][j];}}}}//解释:
/*普利姆算法主要部分是一个双层循环:外层循环内嵌两个并列的单层循环,单层循环内的操作都是常量级别的,因此普利姆算法的时间复杂度为O(n*n)。可见普利姆算法的时间复杂度只与图中的顶点数有关,与边数无关,所以普利姆算法适用于稠密图
*//*** 克鲁斯卡尔算法:每次找出侯选边中权值最小的边,就将该边并入树中。重复此过程直到所有边都被检测完为止。克鲁斯卡尔算法执行过程:将图中该边按照权值从小到大排序,然后从最小边开始扫描各边,病检测当前边是否为侯选边,即是否该边的并入会构成回路,如果不构成回路,则将该边并入当前生成树中,直到所有边都检测完为止。判断是否产生回路需要用到并查集。并查集保存了一颗或者几棵树,这些树有这样的特点:1、通过树中一个节点可以找到器双亲结点,进而找到根结点(其实就是树的双亲存储结构)。这种特性有两个好处:1、一是可以快速地将两棵个含有很多元素的集合合并为一个。两个集合就是并查集中的两棵树,只需要找到其中一棵树的根,然后将其作为另一棵树中任何一个结点的孩子结点即可;2、二是可以很方便地判断两个元素是否属于同一个集合。通过这两个元素所在的结点找到它们的根结点,如果它们有相同的根,则说明它们属于同一个集合,否则属于不同集合。并查集可以用一维数组来简单的表示。*/
struct Road
{int a, b; // a和b为同一条边所连接的两个顶点int w;    // 边的权值static bool  cmp(Road & a, Road & b)  //结构体比较运算子{return a.w < b.w;}};Road road[MAXSIZE];int  v[MAXSIZE];   // 定义并查集数组
int getRoot(int a)  //在并查集中查找根结点的算法
{while (a != v[a]){a = v[a];}return a;
}struct MGraph2
{int n; // 顶点总数int edges;  // 边的总数
};void Kruskal(MGraph2& g,int & sum, Road road[])
{int i = 0; int N = 0, E = 0, a = 0, b = 0;N = g.n;E = g.edges;sum = 0;for (int i = 0; i < N; ++i){v[i] = i;}sort(road, road + E,Road::cmp);        //对road数组的E条边按其权值从小到大进行排序for (i = 0; i < E; ++i){a = getRoot(road[i].a);b = getRoot(road[i].b);if (a != b){v[a] = b;sum += road[i].w;}}}//迪杰斯特拉算法  ; 单源点最短路径
# define INF 1000000000
//dist[vi]表示当前已找到的从v0到每个终点vi的最短路径的长度
//path[vi]保存的是从v0到vi最短路径上vi的前一个顶点,初始值为:若v0到vi有边,则path[vi] = v0,否则path[vi] = -1
//set[]为标记数组,set[vi] = 0表示vi没有被纳入最终的最短路径集合中,否则表示vi已经被纳入到最短路径中
void DijKstra(MGraph& g, int v, int dist[], int path[])
{int set[MAXSIZE];int min = 0, i = 0, j = 0, u = 0;//初始化操作for (int i = 0; i < g.n; ++i){dist[i] = g.edges[v][i];set[i] = 0;if (g.edges[v][i] < INF){path[i] = v;}else{path[i] = -1;}}//关键操作开始for (i = 0; i < g.n ; ++i){min = INF;//下面这个循环每次从剩余顶点中选出一个顶点,通往这个顶点的路径在通往所有剩余顶点的路径中是长度最短的for (j = 0; j < g.n; ++j){if (set[j] == 0 && dist[j] < min){min = dist[j];u = j;}}set[u] = 1; // 将选出的顶点并入到最短路径中//下面这个循环以刚并入的顶点为中间点,对所有通往剩余顶点的路径进行检测for (j = 0; j < g.n; ++j){//下面这个if语句会判断顶点u的加入是否会出现通往顶点j更短的路径,如果出现,则改变原来的路径及其长度,否则什么都不做if (set[j] == 0 && dist[u] + g.edges[u][j] < dist[j]){dist[j] = dist[u] + g.edges[u][j];path[j] = u;}}//关键操作结束}
}
//迪杰斯特拉算法结束时:dist[]中存放了起点v到其余顶点的最短路径长度,path[]中存放了起点v到其余各顶点的最短路径//弗洛伊德算法 : 多源点最短路径算法(或者说是任意一对顶点之间的最短路径)
//弗洛伊德算法的思想:动态规划
void Floyd(MGraph& g,int Path[][MAXSIZE])
{int i = 0, j = 0, k = 0;int A[MAXSIZE][MAXSIZE];//这个双重循环对数组A[][]和Path[][]进行初始化for (int i = 0; i < g.n; ++i){for (int j = 0; j < g.n; ++j){A[i][j] = g.edges[i][j];Path[i][j] = -1;}}//下面这个三层循环是本算法的主要操作,完成了以k为中间顶点对所有顶点对(i,j)进行检测和修改for (k = 0; k < g.n; ++k){for (i = 0; i < g.n; ++i){for (j = 0 ; j < g.n; ++j){if (A[i][j] > A[i][k] + A[k][j]){A[i][j] = A[i][k] + A[k][j];Path[i][j] = k;}}}}}

考研数据结构 图的四种算法 ---- 来自天勤高分笔记相关推荐

  1. 图论:图的四种最短路径算法

    目录: 1.DFS(单源最短路径算法) 例题1: DFS题目分析: 代码DFS: 2.Floyed(时间复杂度On^3) 1.应用场景: 2.解析算法: 核心代码1: 我的笔记 核心代码2: Floy ...

  2. 3.1.5 操作系统之动态分区分配的四种算法(首次适应算法、最佳适应算法、最坏适应算法、临近适应算法)

    文章目录 0.思维导图 1.首次适应算法 2.最佳适应算法 3.最坏(大)适应算法 4.临近适应算法 5.四种算法归纳比较 0.思维导图 本篇文章是对上一篇文章内存的分配与回收提到的动态分区分配算法的 ...

  3. java实现子序列最大和_算法入门:最大子序列和的四种算法(Java)

    最近再学习算法和数据结构,推荐一本书:Data structures and Algorithm analysis in Java 3rd 以下的四种算法出自本书 四种最大子序列和的算法: 问题描述 ...

  4. ML之DTRFRExtraTRGBR:基于四种算法(DT、RFR、ExtraTR、GBR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能

    ML之DT&RFR&ExtraTR&GBR:基于四种算法(DT.RFR.ExtraTR.GBR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自 ...

  5. 求解最大流的四种算法介绍、利用最大流模型解题入门

    求解最大流的四种算法介绍.利用最大流模型解题入门 上一篇中介绍了网络流的基础,最大流最小割定理的证明,下面来看如何求一个容量网络的最大流,这里介绍四种算法:EK算法.SAP算法.DINIC算法.HLP ...

  6. 四种算法求最大公约数

    四种算法求最大公约数(C++) 一. 实验目的 明确算法的概念和特点. 通过对问题的分析,设计合理的算法解决问题: 二. 实验内容 运行最大公约数的常用算法,并进行程序的调式与测试,要求程序设计风格良 ...

  7. 图的四种最短路径算法

    本文总结了图的几种最短路径算法的实现:深度或广度优先搜索算法,弗洛伊德算法,迪杰斯特拉算法,Bellman-Ford算法 1),深度或广度优先搜索算法(解决单源最短路径) 从起始结点开始访问所有的深度 ...

  8. 最大公约数的四种算法

    一.题目分析 运行最大公约数的常用算法,并进行程序的调式与测试,要求程序设计风格良好,并添加异常处理模块(如输入非法等).用四种方法进行运算. 1.辗转相除法: 其算法过程为:设两数为a,b设其中a ...

  9. spi协议时序图和四种模式实际应用详解

    大家好,我是无际. 上个章节我们讲解了spi接口定义,今天我们更加深入讲解下spi协议时序图和spi四种模式的用法. 刚开始接触单片机开发时,最怕就是看时序图,对于我来说就是奇怪的知识. 特别是SPI ...

最新文章

  1. Caused by SSLError(“Can‘t connect to HTTPS URL because the SSL module is not available)
  2. 布道微服务_07服务调用追踪
  3. MATLAB-M文件
  4. Visual Studio Code / 开启自检文本编码方式的方法
  5. java oracle 图片_JAVA读取Oracle中的blob图片字段并显示
  6. python网络编程项目_python网络编程(1):客户端与网络编程简介
  7. 子集生成算法——增量构造法
  8. 读入字符串/字符 scanf与getchar/gets区别
  9. nodeJS之二进制buffer对象
  10. 修改vCenter client无法连接
  11. SAP 严重漏洞可导致供应链攻击
  12. 【Vegas原创】红烧肉的做法
  13. 7-1 宿舍谁最高? (20 分)
  14. 计算机英语演讲主题ppt模板,英文演讲主题PPT模板
  15. C语言 fread 函数 - C语言零基础入门教程
  16. STM32单片机+proteus8仿真的简易交通灯设计
  17. 【单片机仿真】(五)寻址方式 — 立即寻址与寄存器间接寻址
  18. 数据分析师常用工具有哪些?初学者必看
  19. 锁存器和缓冲器的区别
  20. /etc/issue和/etc/motd

热门文章

  1. Daily English Dictation Number One
  2. 【面试总结】小灰灰求职进行曲(五)HR面试常见问题
  3. 在计算机系统内部使用的汉子编码是,数据库系统工程师考试汉字编码输入码
  4. WRF namelist.input记录
  5. 链塔智库联合赛迪区块链发布中国区块链百强榜
  6. OFDMA/SC-FDMA原理及在5G中应用
  7. java绘制三维曲线_使用JFreeChart绘制2D和3D折线图 | 学步园
  8. 【PHP】如何提高网页加载速度?
  9. RK3399 Android7.1修改系统串口设备的权限
  10. 勉力坚持必有丰厚产出, OpenStack Days China见证开源的力量