16.数据结构-3

》〉》〉》〉》〉》算法的度量:
假设CPU在短短几年间,速度提高了100倍,这其实已经很夸张了。而我们的某个算法本可以写出时间复杂度是O(n)的程序,却写出了O(n2)的程序,仅仅因为容易想到,也容易写。即在O(n2)的时间复杂度算法程序下,速度其实只提高了10倍

《1》算法设计的要求:
1.正确性:是指算法至少应该具有输入输出和加工处理无歧义性,能正确反映问题的需求,能够得到问题的正确答案。
正确概念分为四个层次:
1.算法程序没有语法错误,2,算法程序对于合法的输入数据能够产生满足要求的输出结果,
3,短发程序对于非法的输入数据能够得出满足规格说明的结果,4.算法程序对于精心选择的,甚至刁难的测试数据
都有满足要求的输出结果。
1要求最低,仅仅没有语法错误谈不上好的算法,4时最困难的,3作为一个算法是否正确的标准。
2.可读性:算法设计另一目的是为了便于阅读,理解,交流。
3.健壮:输入数据不合法的时候,应该也作出相关处理,而不是产生异常或莫名其妙的结果。
4.时间效率高,存储量低。最少的存储空间,花最少的时间办成同样的事,就是好的算法。
《2》
1.事后统计方法:
这种方法,主要是通过设计好的测试程序和数据,利用计算机计时器,对不同算法编制的程序运行的时间进行比较
2. 事前分析方法:
计算机程序编制前,依据统计方法对算法进行估算。
1.算法采用的策略,方法,2,编译产生的代码质量。3.问题的输入规模。4.机器执行指令的速度。
第一条当然是算法好坏的根本,第二条软件来支持,第四条看硬件。
一个程序的运行时间,依赖于算法的好坏和问题的输入规模。输入规模是指输入量的多少


4241DC33-0358-4A06-9511-201266C7122E.png

测试运行时间最可靠的方法就是计算对运行时间有消耗的基本操作的执行次数,运行时间与这个计数成正比。


40C6E04B-23E8-4C9A-A586-1877674A03E6.png

“求和算法的第一种,求1+2+...+n需要一段代码运行n次。那么这个问题的输入规模使得操作数量是f(n)=n,显然运行100次的同一段代码 规模是运算10次的10倍。而第二种,无论n为多少,运行次数都为1,即f(n)=1;第三种,运算100次是运算10次的1000倍。因为它是 f(n)=n2。

图像.png

《3》函数的渐近增长
比较案例:“判断一个算法好不好,我们只通过少量的数据是不能做出准确判断的”
1.“共2n+3次操作。算法B要做3n+1次操作”


图像.png

“随着n的增大,后面的+3还是+1其实是不影响最终的算法变化的,例如算法A′与算法B′,所以,我们可以忽略这些加法常数”。

2.“算法C是4n+8,算法D是2n2+1(如表2-8-2所示)。”


图像 2.png

“当n≤3的时候,算法C要差于算法D(因为算法C次数比较多),但当n>3后,算法C的优势就越来越优于算法D了,到后来更是远远胜过。而当后面的常数去掉后,我们发现其实结果没有发生改变。甚至我们再观察发现,哪怕去掉与n相乘的常数,这样的结果也没发生改变,算法C′的次数随着n的增长,还是远小于算法D′。也就是说,与最高次项相乘的常数并不重要。”

3.
图像 3.png

“当n=1的时候,算法E与算法F结果相同,但当n>1后,算法E的优势就要开始优于算法F,随着n的增大,差异非常明显。通过观察发现,最高次项的指数大的,函数随着n的增长,结果也会变得增长特别快。

4.算法G是2n2,算法H是3n+1,算法I是2n2+3n+1(如表2-8-4所示)。”
“这组数据应该就看得很清楚。当n的值越来越大时,你会发现,3n+1已经没法和2n2的结果相比较,最终几乎可以忽略不计。也就是说,随着n值变得非常大以后,算法G其实已经很趋近于算法I。于是我们可以得到这样一个结论,判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高阶项)的阶数。

图像 4.png

《3》算法时间复杂度
<1>.算法执行时间的增长率和fn的增长率相同,称为渐近时间复杂度,时间复杂度。O()
指导大O阶:
1.用常数1取代运行实践中的所有加法常数
2.在修改后的运行次数函数中,只保留最高阶项
3.如果最高阶项存在且不是1 ,则去除与这个项相乘的常数。

<2>常数阶:


CBCFC39A-F8BA-45D7-B2FA-EEB13EDC98A5.png

511F60FF-6C3D-41F5-9955-0457EAE593D6.png

<3>线性阶


462BC6CAB549B773632C8708B94676E4.png

<4>对数阶
FC10F046540189B41D1708A29B3B744E.png

<5>平方阶 时间复杂度为O(n2)。
DD53642885F2AA67B75870C9E2C45685.png

A9C7A5459E4BEBF89DA6F479A0EF46C1.png

《4》常见时间复杂度


1.jpg

“O(1)O(1) ——— 常数阶
O(logn) ——— 对数阶
O(n) ——— 线性阶
O(nlogn) ——— nlogn阶
O(n2) ——— 平方阶
O(n3) ———立方阶
O(2n) ———指数阶
O(n!) ———阶乘
O(nn ) ——— n的n方

《5》最坏情况与平均情况:
对算法的分析,一种方法是计算所有情况的平均值,这种时间复杂度的计算方法称为平均时间复杂度。另一种方法是计算最坏情况下的时间复杂度,这种方法称为最坏时间,一般在没有特殊说明的情况下,都是指最坏时间复杂度。

《6》算法空间复杂度:
1.我们在写代码时,完全可以用空间来换取时间,比如说,要判断某某年是不是闰年,你可能会花一点心思写了一个算法,而且由于是一个算法,也就意味着,每次给一个年份,都是要通过计算得到是否是闰年的结果。还有另一个办法就是,事先建立一个有2050个元素的数组(年数略比现实多一点),然后把所有的年份按下标的数字对应,如果是闰年,此数组项的值就是1,如果不是值为0。这样,所谓的判断某一年是否是闰年,就变成了查找这个数组的某一项的值是多少的问题。此时,我们的运算是最小化了,但是硬盘上或者内存中需要存储这2050个0和1
2.一般情况下,一个程序在机器上执行时,除了需要存储程序本身的指令、常数、变量和输入数据外,还需要存储对数据操作的存储单元。若输入数据所占空间只取决于问题本身,和算法无关,这样只需要分析该算法在实现时所需的辅助单元即可。若算法执行时所需的辅助空间相对于输入数据量而言是个常数,则称此算法为原地工作,空间复杂度为O(1)

你可能感兴趣的:(16.数据结构-3)