aes算法实现c语言_以C语言实现归并排序为例,谈谈五大常用算法之一的“分治法”...

分治算法,顾名思义就是“分而治之”,即把规模较大的复杂问题拆分为若干规模较小的类似子问题,并逐个解决,最后再将各个子问题的解决结果合并,得到原始问题的结果的方法。这个技巧是很多高效算法的基础,例如快速排序算法、归并排序算法、快速傅里叶变换等等。

24d8db8748c93d8e6280c29cfed89134.png

五大常用算法之分治算法

分治算法的通俗理解

一般来说,规模小的问题比规模大的问题解决起来简单,例如数组排序问题,只有 2 个元素的数组处理起来要比有 2000 个元素的数组简单。这是分治算法的基本立足点,也是使用条件之一,总结一下就是,对于一个规模较大的问题,可以拆分成若干不相关的子问题,并且子问题解决起来更加简单。

分治算法在我们日常生活中无处不在,例如国家依次划分为省市县镇村来管理,本质上也是因为解决“子问题”(管理村)要简单许多。

有这样一个非常经典的问题:生产线生产了 99 个工件,其中 1 个工件是劣品,比其他 98 个工件质量轻一些,如果用天平称,至少多少次一定能找到这个劣品工件?

要解决这个问题,最简单粗暴的方法是逐个比较,如果第 x 个工件比第 y 个工件轻,第 x 个工件就是劣品。那么 99 个工件至少需要比较 50 次才能确保一定找到劣品。

6998984705a941cf072db442031eac01.png

逐个比较

能够发现,使用逐个比较的方法的时间开销与工件总数有关,如果工件总数很少,比如只有 2 个,那么只需要比较一次就可以找到劣品了。因此该问题满足使用“分治算法”的必要条件之一:规模较小的子问题解决起来更简单。现在尝试使用分治算法解决该问题:

  1. 将 99 个工件等分为 3 份,每份 33 个工件;
  2. 比较第 1、2 份,如果天平平衡,那么劣品必定在第 3 份中,否则劣品在轻的那一份中;
  3. 将劣品所在的那一份再等分为 3 份,每份 11 个工件;
  4. 重复第 2 步;
  5. 将劣品所在那一份再分为 3 份,每份分别为 3、3、2 个工件;
  6. 重复第 2 步;
  7. 不管劣品所在那一份为 3 个工件还是 2 个工件,只需再比较一次,就可找到劣品。

可见,使用分治算法只需要比较 4 次就可以找到劣品,这远低于逐个比较法的 50 次。不过也应该注意到,使用分治法找劣品时,每次拆分子问题时,各个子问题是互不干扰的——例如其中一份的 33 个工件质量不会影响其他份的 33 个工件质量。

归并排序法

从前面这个简单的实例可以看出,分治法有时的确能够极大的提升解决问题的效率,事实上,在C语言程序开发中,许多优秀的算法本质上都是基于分治思想的,一个非常典型的例子就是归并排序法,它在处理数组排序时有着不错的效率。

在处理数组排序时,如果数组中只有 1 个元素,那么该数组本身就可看作是排好序的数组。如果数组中有 2 个元素,那么最多只需比较一次就可以得到排好序的数组。这其实是归并排序法的核心,也即规模越小的数组,对其排序越简单。下图是一个长度为 5 的数组,为了排序,先把它拆分到不能继续拆为止。

7c8f4efb6c15c84410c47f6ae3928246.png

拆分到不能继续拆

显然,“拆分到不能继续拆”后,子问题已经变成了只有 1 个元素的数组,这样的数组已经是“排好序”的数组了。按照我们前面讨论的,现在需要做的就是把这些已经排好序的子数组合并,问题转化为:按照顺序合并有序数组,如下图所示:

48bd912335374aa57f793c2f94faba25.png

按照顺序合并有序数组

归并排序的C语言实现

根据前面的分析,使用C语言实现归并排序法需要实现两个子模块:拆分和合并。拆分数组有多种方法,通常采用二等分法,设数组头的索引为 start,数组尾的索引为 end,mid=(start+end)/2,每次平均拆分,都会将数组分为 start 到 mid,和 mid+1 到 end 两个子数组,再对这两个子数组执行同样的拆分,一直到不能拆分为止。所谓“不能拆分”,其实就是数组中只有一个元素,也即 start 等于 end,这一过程非常适合使用递归实现。我们先确定递归的停止条件:

void divide(int *arr, int start, int end){    if (start >= end)        return;}

否则,我们将继续拆分子数组(start, mid)和(mid+1, end),这一过程的C语言代码如下:

void divide(int *arr, int start, int end){    if (start >= end)    return;    int mid = (start+end)/2;    divide(arr, start, mid);    divide(arr, mid+1, end);}

关于 divide() 递归函数的理解,我之前的这篇文章详细讨论过。

搞定拆分模块后,再来看看合并模块。按照前面讨论的,拆分到“不能拆为止”的都可认为是已经排好序的子数组,所以合并模块要按照顺序(本例从小到大)将子数组合并:

int merge(int *arr, int start, int mid, int end){    int ln = mid-start +1;    int rn = end - mid;    int left[ln], right[rn];        for (int i=0; i
d2727829b81bd9a82d085fd0545656e9.png

C语言代码1

我们先将要合并的拆分后的两个子数组分别保存在 left 和 right 数组里,应注意,这里使用了C语言的变长数组语法,因此在编译时要指定-std=c99选项。接着,我们逐个比较 left 和 right 中的元素,按照顺序填入 arr,这一过程的C语言代码如下所示:

int merge(int *arr, int start, int mid, int end){...    int i=0, j=0, k=0;    for (k = start; i < ln && j < rn; ++k) {        if (left[i] < right[j]) {            arr[k] = left[i];            ++i;        } else {            arr[k] = right[j];            ++j;        }    }
833fcfb27b4a000e2f051be0f848a100.png

C语言代码2

执行完毕后,left 和 right 中可能还有剩余元素,这些剩余元素必定是需要放在 arr 后部分的,因此C语言代码可以如下写:

int merge(int *arr, int start, int mid, int end){...    if (i < ln)        for (; i < ln; i++) {            arr[k] = left[i];            ++k;        }    if (j < rn)        for (; j < rn; ++j) {            arr[k] = right[j];            ++k;        }}
905c0e66dad7b5a786cbb067b53b4ebe.png

C语言代码3

到这里,merge() 函数就完成了,将之与 divide() 函数组合起来,也即:

void divide(int *arr, int start, int end){    if (start >= end)    return;    int mid = (start+end)/2;    divide(arr, start, mid);    divide(arr, mid+1, end);    merge(arr, start, mid, end);}
4fde888338a0faf3f74e37127867f1ab.png

C语言代码4

现在 divide() 函数便可对输入的数组 arr 排序了。

测试归并排序法

这里使用 8 个元素的数组做测试:

int main(){    int arr[8] = {1, 3, 2, 5, 8, 7, 6, 4};    divide(arr, 0, 7);    for (int i=0; i<8; i++)        printf("%d ", arr[i]);    printf("");    return 0;}
9e2d728e2ae3f4e28d62f849b27580b0.png

C语言代码5

编译并执行这段C语言代码,得到如下输出:

# gcc t.c -std=c99# ./a.out 1 2 3 4 5 6 7 8

归并排序算法的时间复杂度

在计算过程中,累加和比较的过程是关键操作,一个长度为 n 的数组在递归的每一层都会进行 n 次操作,分治法的递归层级在 logN 级别,所以整体的时间复杂度是 O(nlogn)。

归并排序法是一个效率不错的排序算法,可能时间复杂度看起来不是特别直观,我们将之与简单粗暴的“冒泡排序算法”对比,在我的机器上分别对不同规模的数组排序,得到如下结果:

7c58ffa3769235ac84f961623cd7fbfa.png

排序效率对比

冒泡排序算法是比较简单的算法,在处理规模较小的数组时和归并排序法的效率不相上下,但是在处理规模较大的数组时,冒泡排序算法的效率逐渐远离归并排序了,且数组的规模越大,二者的效率差异越大,在处理 100 万个数组元素时,归并排序算法仅消耗 230 毫秒就处理完毕了,而冒泡排序算法在执行 2 分钟后仍然还没有完成,我没有耐心等下去,提前结束它了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/305470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一朝读码深似海,不读源码薪难升!读懂.NET5源码,到底多重要?

谈到源码分析&#xff0c;很多人会有这样的疑问&#xff1a;“.NET5的基本功能我已经掌握了&#xff0c;还有读源码的必要吗&#xff1f;”实际上&#xff0c;阅读源码不仅能够帮你更深刻地理解底层设计原理&#xff0c;提升你的系统架构能力和编码功力&#xff0c;还能让你知道…

使用SQL语句获取SQL Server数据库登录用户权限

返回一个报表&#xff0c;报表中包含当前数据库中某对象的用户权限或语句权限的信息。语法sp_helprotect [ [ name ] object_statement ][ , [ username ] security_account ][ , [ grantorname ] grantor ][ , [ permissionarea ] type ]参数[name ] object_statement是当…

如何在 ASP.Net Core 使用 分布式缓存

ASP.Net Core 提供了多种类型的缓存&#xff0c;除了内存缓存和响应缓存之外&#xff0c;还提供了对 分布式缓存 的支持。在之前的一篇文章中&#xff0c;我讨论了 ASP.Net Core 的内存缓存。在本文中&#xff0c;我们将讨论如何在 ASP.Net Core 中使用分布式缓存&#xff0c;本…

50万数据生成6位数不重复字符串_R语言系列3:高级数据管理

R语言系列3&#xff1a;高级数据管理此文内容为《R语言实战》的笔记&#xff0c;人民邮电出版社出版。从高中电脑课学VB开始&#xff0c;大一课内开始学习C&#xff0c;到后来大二为了数模学习Matlab&#xff0c;到大三为了搞深度学习自学Python&#xff0c;到研究生之初学习St…

ぁ。。。爱。。。ぁ

有一老夫妻年逾50.经济条件不错&#xff0c;理当是安享退休的时候&#xff0c;却一起到律师那要办离婚。原因是自从结婚以来&#xff0c;两人争吵不断&#xff0c;老是意见不合。个性上又南辕北辙十分不和谐。二十多年的婚姻生活&#xff0c;要不是为了孩子着想&#xff0c;早就…

python对象_查找Python对象具有的方法

您似乎可以使用此代码,将“对象”替换为您感兴趣的对象&#xff1a; object_methods [method_name for method_name in dir(object) if callable(getattr(object, method_name))] 我在this site发现它.希望这应该提供更多细节&#xff01; 对于那些获得AttributeErrors的人&am…

fcn网络训练代码_另辟蹊径,中科院自动化所等首次用图卷积网络解决语义分割难题...

使用 CNN 处理图像问题已经是常规操作&#xff0c;但此类方法会造成局部位置信息的损失。如何解决这个问题呢&#xff1f;来自中科院自动化所和北京中医药大学的研究者另辟蹊径&#xff0c;提出用图卷积网络解决语义分割问题。选自arXiv&#xff0c;作者&#xff1a;Yi Lu等&am…

盘点大厂的那些开源项目 - 小米科技

小米是一家以手机、智能硬件和IoT平台为核心的互联网公司&#xff0c;以智能手机、智能电视、笔记本等丰富的产品与服务。致力于让全球每个人都能享受科技带来的美好生活。“为发烧而生”是小米的产品概念。“让每个人都能享受科技的乐趣”是小米公司的愿景。小米公司应用了互联…

python做一个单项选择题系统_(完整版)python选择题word打印版

Python 单选题库 一、 python 语法基础 1 、 Python 3.x 版本的保留字总数是 A.27 B.29 C.33 D.16 2. 语言保留字的是 Python 不是 &#xff0c; 以下选项中 A while B pass C do D except 3. 以下选项中描述错误的是 &#xff0c; 程序格式框架 Python 关于 A Python 语言不采…

博主应邀参加YOCSEF虚拟化技术论坛

发布日期: 2007-11-18 中国计算机学会青年计算机科技论坛<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />CCF Young Computer Scientists & Engineers ForumYOCSEF于<?xml:namespace prefix st1 ns "urn:schema…

python中truncate的用法_在Python中操作文件之truncate()方法的使用教程

truncate()方法截断该文件的大小。如果可选的尺寸参数存在&#xff0c;该文件被截断(最多)的大小。大小默认为当前位置。当前文件位置不改变。注意&#xff0c;如果一个指定的大小超过了文件的当前大小&#xff0c;其结果是依赖于平台。注意&#xff1a;此方法不会在当文件工作…

聊聊如何构建一支自驱团队(二)

曾经有一位大佬分享他组建技术团队的心得&#xff0c;当时我问了他一个问题&#xff1a;请问你组建的团队是项目型组织&#xff0c;还是职能型组织。但是大佬似乎对于这个问题没有特别直接的回答&#xff0c;所以在这篇博客中&#xff0c;我想跟大家讨论一下这个问题。一&#…

自定义依赖注解无效_最详细的自定义Spring Boot Starter开发教程

1.前言随着Spring的日渐臃肿&#xff0c;为了简化配置、开箱即用、快速集成&#xff0c;Spring Boot 横空出世。目前已经成为 Java 目前最火热的框架了。平常我们用Spring Boot开发web应用。Spring mvc 默认使用tomcat servlet容器&#xff0c; 因为Spring mvc组件集成了spring…

问题解答集

目录 问题解答集 1 目录 2 修订历史纪录 3 1 什么是.net 4 1.1 .net的定义 4 1.2 什么是C# 4 1.3 C#与C&#xff0c;C的相同之处 5 2 有关Update程序 6 2.1 WinForm中Button控件的使用 6 2.2 将double类型的变量保留固定位数的小数部分 7 …

thinkpadt450s换键盘视频_ikbc c87 入门级有线机械键盘测评

大家好&#xff0c;我是胖虎。今天&#xff0c;写一写我当初买的第一把机械键盘「ikbc c87 茶轴」&#xff0c;非常好的入门级樱桃轴键盘&#xff0c;手感和键帽都很不错。ikbc c87 茶轴机械键盘小白&#xff0c;第一款入门级机械键盘买什么&#xff1f;这款ikbc c87和高斯 87C…

如何在 ASP.Net Core 中使用 条件中间件

ASP.Net Core 是微软开源的跨平台、可扩展、轻量级的模块化框架&#xff0c;可用于构建高性能的web应用程序。中间件组件可以注入到 ASP.Net Core 请求管道中实现对 Request 和 Response 的定制和修改。ASP.Net Core 中间件可以用于检查、路由或者修改流转于Pipeline的Request和…

solidity payable_以太坊区块链搭建与使用(五)-智能合约Solidity

一、智能合约Solidity开发工具1、remix-ide http://remix.ethereum.org/ 在线版本&#xff0c;也可以去github下载安装到本地。开发、编译、发布、执行、测试2、remix-ide-cn http://remix.hubwiz.com/ 在线中文版本&#xff0c;也可以去github下载安装到本地。支持开发、编译、…

Disable anchor tag的javascript代码(兼容IE和Firefox)

对于anchor tags(<a></a>)&#xff0c;IE支持一个非标准的"disabled"属性&#xff0c;但支持也不完善&#xff0c;比如&#xff0c;如果这个anchor tage没有 "href" 值&#xff0c;IE会把这个anchor设置为灰色&#xff0c;当然不能点击&#x…

大气校正后的ndvi_大气校正常见错误处理方法及校正后检查

本文汇总了ENVI FLAASH大气校正模块中常见的错误&#xff0c;并给出解决方法&#xff0c;分为两部分&#xff1a;运行错误和结果错误。前面是错误提示及说明&#xff0c;后面是错误解释及解决方法。FLAASH对输入数据类型有以下几个要求&#xff1a;1、波段范围&#xff1a;卫星…

dotnet cli 5.0 新特性——dotnet tool search

dotnet cli 5.0 新特性——dotnet tool searchIntro.NET 5.0 SDK 的发布&#xff0c;给 dotnet cli 引入了一个新的特性&#xff0c;dotnet tool search&#xff0c;主要用于搜索 Nuget 上的 dotnet tool&#xff0c;这个命令会搜索 tool 的名称以及一些元数据&#xff0c; tit…