目录

  • 前言
  • 一、算法思想分析
  • 二、算法效率分析
  • 三、算法代码
    • C语言代码
  • 后记

前言

在上一篇文章中,我们聊了聊KMP算法,一个极其高效但又非常难以理解(个人看来)的算法,如果有朋友想要深度讨论,欢迎私信。
本篇我们来聊聊prim算法,我最早接触prim算法已经记不清是数据结构课中还是离散数学课中了,但即便科目不同,prim算法还是那个prim算法。
prim算法是一种用于在连通图中获取最小生成树的算法同样用于获取最小生成树的算法还有Kruskal算法(大家有兴趣同样可以了解了解,但其实二者是比较相似的),prim算法属于贪心算法的一种,至于为什么,或许在分析其过程的时候大家就明白了。
要理解prim算法,大家首先要理解好什么是连通图?什么是最小生成树?这里我们来简单介绍一下,因为这不是我们本次的重点(如果已经有基础的朋友,可以适当跳过)。

  • 什么是连通图?,首先理解什么是图?(这里面的学问其实有点大,所以我说咱们就是简单介绍下哈,本篇文章还是对有基础的朋友较友好,因为对于有基础的朋友,我可能是在废话哈哈哈)简单来说,平面内许多点通过一些路径相互连接(不一定要全部连接),就构成了一个图,而根据这些点之间的路径是否有方向,又分为了无向图和有向图。如下图,分别是一种无向图和有向图。

    那么?什么是连通图呢?简单来说(只能简单来说了,说多了可以另起一篇文章。。。),就是图中的点通过图中的某些路径(带方向的就必须按照方向来)可以抵达任意一个点。最为简单的模型就是一个地区的许多村落之间的通信,如果每个村庄之间都可以达成通信,就是连通的。

  • 最小生成树是什么呢? 连通图中,每条路径都存在一个权值(理解为距离/成本也行吧,但其实不是这么理解的)。从该连通图出发,寻找一个路径数最少,但每个点之间都可达,就是一个生成树了(专业术语是连通无环子图)。生成树不止一个,而所以生成树中权值之和最小的生成树称为最小生成树。

以上是对最小生成树的简单介绍,如果大家想详细了解一下,可查询资料,这些都不是我们本次的重点。如下给出《算法设计与分析基础》中生成树和最小生成树的定义。

如下为一些例子:

一、算法思想分析

在简单讲解最小生成树的概念后,我们来聊聊prim算法的思想。前面提到过,prim算法是贪心算法的一种,而贪心算法,讲究的就是要极力满足当前最优,这个当前最优正是prim算法的核心思想。
首先,prim算法中存在两个存储空间, 一个用来存放已加入最小生成树的顶点,而另外一个则用来存放还未加入最小生成树中的顶点。 当连通图中所有顶点已放入用于最小生成树的空间中,那么我们最小生成树算法结束!

  • 算法开始,起始顶点可随机找或指定一个。将起始顶点先放入已选顶点集合中
  • 未放入已选顶点集合中查找一条已选顶点集合中所有点最短(或者是权值最小,这里看自己理解了)的路径(说是一条线或许更合适吧)。刚开始的话,我们已选顶点集合只有一个点!而之后我们会将未加入的顶点一个一个加入已选顶点集合,所以这里的条件必须是已选顶点集合中所有点。显然,在我们找到的这条最短(权值最小)路径的两端的顶点,一个肯定属于还未加入最小生成树中的顶点,另一个肯定属于已加入最小生成树的顶点。将还未加入已选顶点集合的那个点,加入已选顶点集合,本轮任务完成。如果需要路径的,可以将路径记录保存下来。
  • 重复第二步,直到所有顶点已加入已选顶点集合,那么,我们的最小生成树就完成了。如果需要计算最小生成树的权值之和,在每一次找到最短路径的时候求一次和即可,需要具体路径的进行标记即可。

接下来,我们举个栗子来做个示范:






该例后续代码将会用到,大家可以自行看看该例。

二、算法效率分析

prim算法的具体效率,是与图的顶点和边数都是有关的。《算法设计与分析基础》中是这么分析的:

以上是一种高级的分析,我们就简单来点吧。
假设总共又n个顶点,那么我肯定有n次比较过程!而在第k次比较过程中,又有n-k个点和另外n-k个顶点相互比较,那么总结起来,那么算法复杂度几乎再n的立方级别。或许有朋友问了,这么算起来,好像也不是很高效哦?n³级别复杂度的确不是很高,但其实prim算法真正效率是介于n²和n³之间的,因为我们如上的分析是一种最坏的情况,就是每个点之间都存在一条路径。
再者,相比于穷举法(也就是蛮力法)来查找最小生成树,prim算法已是大大提升了。《算法设计与分析基础》中这样写到:

三、算法代码

C语言代码

这里我们图的表示用邻接矩阵来表示,具体请看代码极其注释:

/*最小生成树 prim算法 从一个连通图中获取一个最小生成树*/
/*
输入要求:输入一个连通图 存储模式:邻接矩阵表示 0表示不可达  点依次默认命名为a,b,c,d,e,f,g...
例如:n*n数组
6
0 1 0 0 6 5
1 0 1 0 0 4
0 1 0 6 0 4
0 0 6 0 8 5
6 0 0 8 0 2
5 4 4 5 2 0
即为一种输入 实际上为上课讲解时的连通图表示
输出要求: n-1长度数组 包含n-1条路径 ()表示的为m号点到k号点的那条路径
(1,2) (2,3) (2,6) (6,5) (6,4)
最小生成树权值之和:1+1+4+5+2=13
*/
#include<stdio.h>
#define MAXN 1000
/*二维数组存储 采用邻阶矩阵数据*/
int input[MAXN][MAXN];
int sign[MAXN]= {0}; // 标记sign数组 初始化全为0 ,1表示已经加入已选列表
int prime(int n) {int sum=0; // 最小生成树权值之和 初始值为0/* 默认从第一个点开始 */sign[1]=1;int counter=1; // 计算当前状态已加入最小生成树队列的个数int flagX=-1,flagY=-1,minNodeValue=1000000;while(counter!=n) {flagX=-1,flagY=-1,minNodeValue=1000000; // 每一次都要初始化 /* 每一次循环都是一次贪心 当前局势的一种最优解 */for(int i=1; i<=n; i++) {if(sign[i]==0) continue; // 如果当前为加入队列 直接下一次循环 其实这是一个笨方法for(int j=1; j<=n; j++) {// 在查找下一个连接点时 发现这个连接点已经在里面了(或者为0,即不可达) 我们直接跳过 我能说这是一个笨方法么?但似乎只能这样if(sign[j]==1||input[i][j]==0) continue;if(input[i][j]<minNodeValue){// 更小的一个进行标记flagX=i;flagY=j;minNodeValue=input[i][j]; }}}/* 一轮查找后 */sign[flagY]=1; // 谁该标1 要清楚counter++; // 找到加一 sum+=input[flagX][flagY]; // 这里其实不用担心指针越界 如果是连通图 在一轮查找下来 肯定能找到一个最小的 printf(" (%d,%d) ",flagX,flagY); // 其实我们都知道 flagX flagY 的位置 在这里顺序不重要 }return sum;
}
int main() {/*作为输入的主函数*/int n;printf("请输入邻接矩阵的维度n:"); scanf("%d",&n);printf("邻接矩阵:\n");for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {scanf("%d",&input[i][j]);}}/*调用函数*/int sum = prime(n);printf("\n最小生成树权值之和:sum=%d\n",sum);
}

代码中有部分存在取巧,如果大家有任何建议都可私信或留言。

后记

经过一番分析,prim算法的效率似乎是接近n³的,可能偏离了大家的预期。但是一个算法的高效,不是在于它的算法复杂度是多少,而是在于这个算法和解决同样问题的其他算法,相比之下,这个算法是否高效。
简而言之,高效算法是相对的,并不是绝对的。如果在解决最小生成树问题有其他算法比prim算法更为高效,那么那个算法也可以称之为高效算法。
以上只是我的理解,如果大家有其他意见和想法,欢迎留言或私信。

算法设计与分析——prim算法相关推荐

  1. 算法设计与分析——蒙特卡罗算法(简单、通俗、易懂)C++

    算法设计与分析--蒙特卡罗算法(简单.通俗.易懂) 虽然都是文字描述,但都是较为通俗的语言,相信你看完应该能理解 在实际应用中会遇到一些问题,不论采用确定性算法还是随机性算法,都无法保证每次能到到正确 ...

  2. 计算机算法设计与分析教学大纲,算法设计与分析的教与学(教学大纲)

    原标题:算法设计与分析的教与学(教学大纲) 课程代码:**** 课程负责人: **** 课程中文名称:算法设计与分析 课程英文名称:Designand Analysis of Algorithms 课 ...

  3. 计算机算法设计与分析读后感,算法设计与分析基础经典读后感有感

    <算法设计与分析基础>是一本由Anany levitin著作,清华大学出版社出版的胶版纸图书,本书定价:49.00元,页数:409,特精心从网络上整理的一些读者的读后感,希望对大家能有帮助 ...

  4. 程振波 算法设计与分析_算法设计与分析

    本书按照教育部*制定的计算机科学与技术专业规范的教学大纲编写,努力与国际计算机学科的教学要求接轨.强调 算法 与 数据结构 之间密不可分的联系,因而强调融数据类型与定义在该类型上的运算于一体的抽象数据 ...

  5. 算法设计与分析 ——插入排序算法与归并排序算法比较

    插入排序算法与归并排序算法比较 实验目的 通过插入排序算法与归并排序算法效率对比体会算法在求解问题中的重要性. 实验内容 分别编写函数实现插入排序算法和归并排序算法: 利用随机函数产生大量数据存入数组 ...

  6. 算法设计与分析_算法设计与分析(第2版)第2章分治策略回顾

    YI时间|外刊|MM-DFW|机器学习系列 点击上方蓝字,关注给你写干货的松子茶 分治策略是通用算法设计技术之一,很多有效的算法是它的特殊实现,顾名思义就是分而治之.一个问题能够用分治法求解的要素是 ...

  7. 算法设计与分析_算法导论(CLRS)骨灰级笔记分享:目录

    倘若你去问一个木匠学徒:你需要什么样的工具进行工作,他可能会回答你:"我只要一把锤子和一个锯".但是如果你去问一个老木工或者是大师级的建筑师,他会告诉你"我需要一些精确的 ...

  8. python 算法设计与分析_算法设计与分析(黄建军)

    spContent=本课基于主讲教师在北京大学讲授数据结构与算法课(Python版)的多年教学实践经验,面向具有Python语言程序设计基础的大学生和社会公众,介绍常见的基本数据结构以及相关经典算法, ...

  9. 算法设计与分析python_Python算法设计与分析

    内容提要 本书内容包括算法初步.排序算法.查找.双指针问题.哈希算法.深度优先搜索算法.广度优先搜索算法.回溯算法.动态规划.贪心算法.分治算法.并查集.最短路径算法和数论算法等常见算法.每个算法都做 ...

  10. 【算法设计与分析】算法的时间复杂度(介绍O渐近上界,Ω渐近下界,θ准确的界)

    什么是时间复杂度? 我们先看看一些函数的渐近表达式: 关于时间复杂度的基本要点: 时间复杂度反映的是随着问题规模的变大,计算所需的时间的增长速度,与系数的多少关系不大 算法的渐近时间复杂度,简称时间复 ...

最新文章

  1. Vector Enumeration
  2. angularjs 路由---angularjs 搭建前端框架
  3. 【Python爬虫】Beautiful Soup库入门
  4. np.c_和np.r_的用法解析
  5. [UWP]理解ControlTemplate中的VisualTransition
  6. Google Chrome不支持ClickOnce部署
  7. LeetCode 939. Minimum Area Rectangle (最小面积矩形)
  8. java获取mysql表的主键_用java如何获取oracle数据库表里面的主键序列
  9. 软件项目中的成本构成及估算方法
  10. 利用Python制作证件照
  11. android打印机字体大小,热敏打印机字体大小设置,怎么设置打印机字体
  12. Flume之生产正确的使用方式二(Multiple Agent+ Multiple Channel+Custom)
  13. 可见光波长和颜色的对应关系
  14. switch语句练习题
  15. 联想新款小新 Pro 27 一体机 评测 怎么样
  16. 5款高逼格实用手机APP推荐,千万不能错过!
  17. 利用MODIS TOOL批量重投影MODIS
  18. 湖北颁发首批测绘资质新证
  19. macbook进水不用怕
  20. 【夜读】影响一生的五大定律内心强大的人,有这五种特质

热门文章

  1. STM32官方固件库(标准固件库)下载及介绍
  2. 桌面高效便捷的多窗口调整管理工具 - AquaSnap
  3. 编译原理第三版 作业一
  4. 浏览器 pad android,安卓平板专享 推荐五款Pad版应用浏览器
  5. 三角形外接圆圆心公式
  6. 学生管理系统数据库设计
  7. ArcGIS for iOS 开发系列(3) – 基础篇-“Hello World Map”
  8. C语言程序设计谭浩强(第四版)期末复习重点
  9. 直插式电阻电容封装与尺寸图…
  10. Flash MX游戏制作常用代码解析