《算法技术手册》一2.2 函数的增长率

简介: 本节书摘来华章计算机《算法技术手册》一书中的第2章 ,第2.2节, George T.Heineman Gary Pollice Stanley Selkow 著 杨晨 曹如进 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 函数的增长率

我们将算法执行时间的增长率描述为一个与输入问题样本规模相关的函数。使用这种方法描述算法性能会比较抽象,因为它忽略了大量的细节问题。所以,在使用这种方法时,需要对抽象背后的细节有一个清醒的认识。程序都必须运行在某个平台上,在这里,广义的平台定义包括:
运行程序的计算机,包括CPU、数据缓存、浮点运算单元(FPU)以及其他芯片特性。
程序编写所使用的编程语言、编译器/解释器以及用于生成代码的优化设置。
操作系统。
其他后台进程。
改变上述组成平台的任何条件都只会对程序的执行时间造成常量级别的影响,因此根据之前提到的渐近等价原理,我们会忽略由平台一致性所导致的性能差异。
为了让函数增长率的讨论拥有更为具体的场景,我们会简要地讨论一下顺序搜索算法,关于这个算法的细节稍后会在第5章讲到。所谓顺序搜索,就是在一个包含n个(n≥1)互异元素的列表中顺序地进行搜索,直至找到想要的值v。我们暂时假设:
列表中的n个元素各不相同。
待查找的元素v一定在列表中。
列表中每个元素都有可能是待查找的元素v。
为了了解顺序搜索算法的性能,我们必须知道待检查的元素总数的“平均值”是多少。由于已知v肯定在列表中,并且每个元素都有可能为v,因此待检查的元素平均数E(n)为:n个元素总共需要检查的个数总和除上n。其数学表示为:
2017_09_19_150411
由此可见,在上述前提下,顺序搜索算法对于n个互异元素所组成的列表需要检查大约一半数量的元素。如果列表中的元素数量翻倍,那么顺序搜索算法需要检查的数量也会大致翻倍。因此,可以将顺序搜索算法期望的检查次数视作一个关于n的线性函数,即“大约”为c*n(其中c是常数,这里c = 0.5)。性能分析的一个基本的观点认为,常数c从长远角度看是不重要的,因为影响性能的最重要因子是问题样本的规模n。随着n越来越大,错误率就会如同下式一样变得不再重要:
2017_09_19_150608
实际上,约等式两侧的比率近似趋向于1,即:
2017_09_19_150720
当然,在n较小时,估算中的误差会比较大。在这样的使用环境下,顺序搜索期望查找的元素数量增长率是线性的。也就是说,当样本规模很大时,我们会忽略常数乘法常量,而主要关注样本的规模。
依据增长率这个抽象的概念选择算法时,需要牢记的是:
常数的重要性
这就是我们使用超级计算机并定期对其升级的原因。
样本规模n并不总是很大
在第4章我们将会看到,快速排序算法执行时间的增长率要低于插入排序算法执行时间的增长率。但是在相同平台下,对于小数据集,插入排序算法表现得要比快速排序算法更好。
算法的增长率决定了算法在逐渐增长的数据集上的性能表现。下面将通过一个更为复杂的例子来解释如何应用这个基本原理。
考虑通过一个特定的分类任务来对四种排序算法进行评估。下述性能数据通过对n个随机字符串进行排序来生成,n的取值范围为1-512。对于每个n的取值,我们都将进行50次实验,并且舍弃掉最好和最坏的实验结果。图2-1展示了剩余48次实验的平均执行时间(单位:n的数据样本上的性能。当然,随便猜想出这样的一个函数是不切实际的,因此我们借助已有的商业软件对结果采用统计方法进行了回归分析,并且根据结果描绘出了一条趋势线。趋势线与实际数据的拟合度设为R2,取值为0-1。R2越趋近于1,表示拟合度越高。例如,R2 = 0.9948表示只有0.52%的概率趋势线和数据不拟合,这是由数据的随机变化而导致的。
第四种排序算法很明显是四种算法中最差的。根据电子数据表上描绘的512个数据点,与其性能相符合的趋势线是:
2017_09_19_152855
可以看到,R2的值非常接近于1,说明这是一个非常精确的预测。第二种排序算法在给定的数据集上性能最好。其性能可以用如下的趋势线来描述:
2017_09_19_153009
第二种排序算法起初只是比第三种排序算法的速度稍快,但最后它比第三种排序算法快了10%。第一种排序算法表现出了两种不同的性能特征。当数据集中的字符串数量不超过39个时,其性能表现为:
2017_09_19_153058
但是,当数据集中的字符串达到40个或者更多时,其性能表现为:
2017_09_19_153126
上述表达式中的系数完全取决于算法运行的平台。就像之前描述过的那样,这些附带的差异并不重要。n的长期变化趋势支配着这些算法的性能。事实上,图2-1中采用了两个不同规模的数据集来诠释算法性能,可以看到,只有当数据集的规模n变得足够大时,算法之间的差异才变得明显。
算法设计人员常常会努力地探索和理解算法之间的性能差异。第一种排序算法展现了Linux 2.6.9内核中快速排序算法qsort的性能。在阅读快速排序算法的源代码时(这些代码可以在任何Linux的代码库中找到),我们注意到了这样的注释:“这个快速排序例程由Bentley和McIlroy设计”。Bentley和McIlroy(1993)描述了如何针对不同的问题规模(如规模小于7、在8和39之间以及达到40或者甚至更大),采用不同的策略对快速排序进行优化。实验结果表明,这个隐藏的优化手段非常有效。
2017_09_19_153154
图2-1:小数据集上四种排序算法的比较结果

相关文章
|
18天前
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
19 0
|
5天前
|
算法 Java C语言
Java中的算法与C语言中的函数
Java中的算法与C语言中的函数
9 2
|
6天前
|
算法 调度 C++
【调度算法】共享函数vs拥挤距离
【调度算法】共享函数vs拥挤距离
15 1
|
11天前
|
SQL 存储 算法
【MySQL技术内幕】6.4-锁的算法
【MySQL技术内幕】6.4-锁的算法
23 1
|
11天前
|
存储 算法 关系型数据库
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
14 1
|
13天前
|
算法 C语言 Ruby
分形逃逸时间算法中的 Normalized Iteration Count(NIC)技术 让颜色更柔和
Normalized Iteration Count (NIC) 技术是一种提升逃逸时间算法中分形图像质量的方法,它产生更平滑的颜色过渡。数学公式表示为:`mu = n + 1 - log(log(|Z(n)|)) / log(p)`,其中 `Z(n)` 是迭代次数,`|Z(n)|` 是复数模长,`p` 通常取2。示例代码提供了 Ruby, Maxima 和 C 语言的实现。
|
15天前
|
存储 自然语言处理 算法
编辑距离算法全解析:优化文本处理的关键技术
编辑距离算法全解析:优化文本处理的关键技术
|
20天前
|
算法 NoSQL Python
开山之作!Python数据与算法分析手册,登顶GitHub!
若把编写代码比作行军打仗,那么要想称霸沙场,不能仅靠手中的利刃,还需深谙兵法。 Python是一把利刃,数据结构与算法则是兵法。只有熟读兵法,才能使利刃所向披靡。只有洞彻数据结构与算法,才能真正精通Python。
|
20天前
|
存储 人工智能 算法
RAG技术的高级应用和算法
文章主要探讨了RAG技术的高级应用和算法,系统化地整理了各种方法。
|
3天前
|
算法 C语言 Python
简单遗传算法优化简单一元函数(python)
简单遗传算法优化简单一元函数(python)
4 0

热门文章

最新文章