《大话数据结构》读后总结(四)
2019-03-22 本文已影响0人
徐曙辉
一、算法
1、算法效率的度量方法
1.1 事后统计方法
- 通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。该方法具有很大缺陷,不予采纳。
1.必须依据算法事先编制好程序,花费时间和人力
2.时间的比较依赖计算机硬件和软件等环境因素,有时会掩盖算法本身的优劣。
3.算法的测试数据设计困难,并且程序的运行时间往往还与测试数据的规模有很大关系,效率高的算法在小的测试数据面前往往得不到体现。
1.2 事后统计方法
- 在计算机程序编制前,依据统计方法对算法进行估算。
- 经过分析,我们发现,一个用高级程序语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:
1.算法采用的策略、方法。
2.编译产生的代码质量。
3.问题的输入规模。
4.机器执行指令的速度。 - 抛开这些与计算机硬件、软件有关的因素,一个程序的运行时间,依赖于算法的好坏和问题的输入规模。所谓问题输入规模是指输入量的多少。
- 下面用两种求和算法进行举例。
第一种
int i, sum = 0,n = 100; /* 执行1次 */
for (i = 1; i <= n; i++) /* 执行了n+1次 */
{
sum = sum + i; /* 执行n次 */
}
printf("%d", sum); /* 执行1次 */
第二种
int sum = 0,n = 100; /* 执行一次 */
sum = (1 + n) * n / 2; /* 执行一次 */
printf("%d", sum); /* 执行一次 */
- 第一种算法,执行了1+(n+1)+n+1次=2n+3次;
- 第二种算法,是1+1+1=3次。
- 事实上两个算法的第一条和最后一条语句是一样的,所以我们关注的代码其实是中间的那部分,我们把循环看作一个整体,忽略头尾循环判断的开销,那么这两个算法其实就是n次与1次的差距。
第三种
int i, j, x = 0, sum = 0, n = 100; /* 执行一次 */
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
x++; /* 执行n×n次 */
sum = sum + x;
}
}
printf("%d", sum); /* 执行一次 */
这个例子中,i从1到100,每次都要让j循环100次,而当中的x++和sum=sum+x;其实就是1+2+3+...+10000,也就是1002次,所以这个算法当中,循环部分的代码整体需要执行n2次。
测定运行时间最可靠的方法就是计算对运行时间有消耗的基本操作的执行次数。运行时间与这个计数成正比。
同样问题的输入规模是n,求和算法的第一种,求1+2+...+n需要一段代码运行n次。那么这个问题的输入规模使得操作数量是f(n)=n,显然运行100次的同一段代码规模是运算10次的10倍。而第二种,无论n为多少,运行次数都为1,即f(n)=1;第三种,运算100次是运算10次的1000倍。因为它是f(n)=n2。
分析一个算法的运行时间时,重要的是把基本操作的数量与输入规模关联起来,即基本操作的数量必须表示成输入规模的函数。
image
随着n值的越来越大,它们在时间效率上的差异也就越来越大。
欢迎扫描下方二维码,持续关注:
image互联网工程师(id:phpstcn),我们一起学习,一起进步