问题样本的规模
问题样本是解决问题的程序所使用的数据集,在大部分问题中,随着已编码样本的规模的增长,程序的执行时间也不断增长。
设计一个高效的算法通常是从选择一个合适的数据结构开始的,数据结构通常是在计算机中表示将要解决的问题。
函数的增长率
不同的编码会在执行时间上产生巨大的差异。同样也告诉设计人员必须根据将要进行的操作选择合理的编码来优化性能。
期望搜索数目可以用c*n来表示,c为常数。关于性能分析的一个基本观点是,在长期的运行中,常数c是不重要的,因为最重要的影响性能的因子是问题样本的规模n,随着n越来越大,那么错误率就如:
所以常数c就变得不重要了,
算法的增长率决定了算法在逐渐增长的大数据集上的性能表现。
最好最坏和平均情况下的性能分析
常数级算法的性能
对数级算法的性能
对数级算法是非常高效的,因为它们能够快速收敛到解。一般来说,这些算法的成功之处在于它们每次将问题的规模缩减一半。
这个猜测算法至多经过k=[log(n)]次迭代便可以得到解,在第i次迭代的时候,算法在 个数中进行猜测。ε可以看做是不确定的个数。在每一次迭代之后,ε缩简一半。
次线性的算法的性能,时间复杂度为
线性算法的性能
nlogn算法的性能
t(n)=2*t(n/2)+O(n)
t(n/2)=2*t(n/4)+O(n/2)
t(n)=2[2*t(n/4)+O(n/2)]+O(n)
归约 t(n)=4*t(n/4)+O(2n)
推广,这个拓展在,也就是k=log(n)时停止。因此可以得到闭合解t(n)=n*c+O(n*log(n))。
因为对于任何常数c来说,n*(log(n))都比c*n要高阶,所以t(n)能够简写为O(nlog(n))。
二次方的算法性能
改变算法的实现来提高效率是不可能超越算法本身固有的二次方性能的。
混合操作
并不是每个操作都能够被优化。事实上,优化一个操作将会降低另外一个操作的执行性能。
手动内存分配
传统的计算机图表中,栈是在内存中“向下增长”,而堆是“向上增长”。
程序执行时不断地调用函数和从函数中返回,执行栈在不断地收缩。所有属于栈的内存都会被自动地回收。但是属于堆的内存是在程序员的控制之下,必须显示地释放。
在多数情况下,如果一个程序释放内存失败,它也许可以继续正常运行(当程序结束时,它使用的内存会被操作系统回收)。