《大话数据结构》

算法效率的度量方法




刚才我们提到设计算法要提高效率。这里效率大都指算法的执行时间。那么我们如何度量一个算法的执行时间呢?正所谓是骡子是马拉出来溜溜,我们通过对算法的数据测试利用计算机的计时功能,来计算不同算法的效率是高还是低。




事后统计方法




这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。
但这种方法显然是有很大缺陷的:
·必须依据算法实现编程好程序,这通常需要花费大量的时间和精力。如果编制出来他根本是很糟糕的算法,不是竹篮打水一场空吗
·时间的比较依赖计算机硬件和软件等环境因素,有时会掩盖算法本身的优劣,要知道,现在一台四核处理器的计算机,跟当年286,386,486等老爷爷辈的机器相比,在处理算法的运行速度上,是不能相提并论的;而所用的操作系统,编译器,运行框架等软件的不同,也可以影响它们的结果;就算是同一台机器,CPU使用率和内存占用率情况不一样,也会造成细微的差异。
·算法的测试数据设计困难,并且程序的运行时间往往还得与测试数据的规模有很大关系,效率高的算法在校的测试数据面前往往得不到体现,比如10个数字的排序,不管用什么算法,差异几乎是0,而如果有100万个随机数字排序,那不同算法的差异就非常大了。那么我们为了比较算法,到底用多少数据来测试,这是很难判断的问题。 基于事后统计方法有这样那样的缺陷,我们考虑不予采纳。




事前分析估算方法





我们的计算机前辈,为了对算法的评判更科学,研究出了一种叫做事前分析估算的方法。在计算机程序编制前,依据统计方法对算法进行估算。经过分析,我们发现,一个用高级程序语言编写的程序在计算机上运行时所耗费的时间取决于下列因素
·算法采用的策略、方法。
·编译产生的代码质量
·问题的输入规模
·机器执行指令的速度
第一条当然是算法好坏的根本,第二条要有软件来支持,第四条要看硬件性能。也就是说,抛开这些与计算机硬件,软件有关的因素,一个程序的运行时间,依赖于算法的好坏和问题的输入规模。所谓问题输入规模是指输入量的多少。我们来看看两种求和的算法:
 
 
显然,第一种算法,执行了1+(n+1)+n+1次2n+3;而第二种算法,是1+1+1=3次,事实上两个算法的第一条和最后一条语句是一样,所以我们关注的代码其实是中间的那部分,我们把循环看作一个整体,忽略头尾循环判断的开销,那么这两个算法其实就是n次与1次的算法。算法好坏显而易见。
我们再来延伸一下上面这个例子:
 
这个例子中,1从1到100,每次都要让j循环100此,而当中的x++和sum = sum + x;其实就是1+2+3+……+10000,也就是100的二次方次,所以在这个算法当中,循环部分的代码整体需要执行n的二次方次。显然这个算法的执行次数对于同样的输入规模 n =100,要多于前面两种算法,这个算法的执行时间随着n的增加也将远远多于前面两个。
此时你会看到,测试运行时间最可靠的方法就是计算对运行时间有消耗的基本操作的执行次数。运行时间与这个计数成正比。我们不关心编写程序所用的程序语言是什么,也不关心这些程序将跑在什么样的计算机中,我们只关心它所实现的算法。这样,不计那些循环索引的递增和循环种植条件,变量声明,打印结果等操作,最终,在分析程序的运行时间时,最重要的是把程序看成是独立与程序设计语言的算法或一系列步骤。
可以从问题描述中得到启示,同样问题的输入规模是n,求和算法的第一种,求1+2+…+n需要一段代码执行n此,那么这个问题的输入规模使得操作数量是f(n)=n,显然运行100次的同一段代码规模是运算10次的10倍。而第二种,无论n为多少,运行次数都为1,即f(n) = 1;第三种,运算100次是运算10次的100倍,因为它是f(n) = n的二次方。
我们在分析一个算法的运行时间时,重要的是把基本操作的数量与输入规模关联起来,即基本操作的数量必须表示成输入规模的函数。
 
我们可以这样认为,随着n值的越来越大, 它们在时间效率上的差异也就越来越大。好比你们当中有些人每天都在学习,我指有用的学习,而不是只为了考试的死读书,每天都在进步,而另一些人,打打游戏,睡睡大觉。入校时大家都一样,但毕业时结果可能就大不一样,前者名企争抢着要,后者求职无门。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值