思考:如果两个算法都满足功能性需求,那工程中最关心的其它特性是什么?如何比较评判呢?

注: 性价比(效率)是工程中最关注的算法附加特性!

算法效率的衡量

事后统计法

  • 比较不同算法对同一组输入数据的运行处理时间
  • 缺陷

    • 为了获得不同算法的运行时间必须编写相应程序
    • 运行时间严重依赖硬件及运行时的环境因素
    • 算法的测试数据选取相当困难

事前分析估算

  • 依据统计的方法对算法效率进行估算
  • 影响算法效率的主要因素

    1. 算法采用的策略和方法
    2. 问题的输入规模
    3. 编译器所产生的代码
    4. 计算机执行速度

算法效率的简单估算一

image.png

算法效率的简单估算二

image.png

算法效率的简单估算三

image.png

实例分析:程序效率估算

#include <iostream>

using namespace std;

int func(int a[], int len)              // ==> (n*n + 2)
{
    int ret = 0;                        // 1
    
    for(int i=0; i<len; i++)     
    {
        for(int j=0; j<len; j++) 
        {
            ret += a[i] * a[j];         // n * n
        }
    }
    
    return ret;                         // 1
}

int main()
{
    int array[] = {1, 2, 3, 4, 5};
    
    cout << func(array, 5) << endl;
    
    return 0;
}
#include <iostream>

using namespace std;

long sum1(int n)            // ==> (2n + 4)
{
    long ret = 0;           // 2
    int* array = new int[n];
    
    for(int i=0; i<n; i++)
    {
        array[i] = i + 1;   // n
    }
    
    for(int i=0; i<n; i++)
    {
        ret += array[i];    // n
    }
    
    delete[] array;         // 2
    
    return ret;
}

long sum2(int n)            // ==> n + 2
{
    long ret = 0;           // 1
    
    for(int i=1; i<=n; i++)
    {
        ret += i;           // n
    }
    
    return ret;             // 1
}

long sum3(int n)            // ==> 3
{
    long ret = 0;           // 1 
    
    if( n > 0 )
    {
        ret = (1 + n) * n / 2;  // 1
    }
    
    return ret;             // 1
}

int main()
{
    cout << "sum1(100) = " << sum1(100) << endl;
    cout << "sum2(100) = " << sum2(100) << endl;
    cout << "sum3(100) = " << sum3(100) << endl;
    
    return 0;
}

启示

  • 程序效率估算练习中的关键部分的操作数量为 n * n
  • 三种求和算法中关键部分的操作数量分别为 2n,n 和 1

随着问题规模 n 的增大,它们操作数量的差异会越来越大,因此实际算法在效率上的差异也会变得非常明显

image.png

算法操作数量的对比一

image.png

结论:

  • n <= 3 时,算法B(2n2 + 1)优于算法A(4n+8)
  • 当 n 越来越大的时候,算法A(4n+8)相对算法B(2b2+1)优势明显

算法操作数量的对比二

image.png

结论:

  • 当 n == 1 时,算法C(2n2 + 3n + 1) 和算法D(2n3 + 3n + 1) 的操作数量相同
  • 当 n 越来越大的时候,算法 C(2n2 + 3n + 1)的效率远高于算法D(2n3 + 3n+ 1)

算法操作数量的对比三

image.png

结论:

  • 判断一个算法的效率时,操作数量中的常数项和其他次要项常常可以忽略,只需要关注最高阶就能得出结算

小结

  • 算法的度量有事后统计法和事前分析估算法
  • 事后统计法不容易准确度量算法的效率
  • 事前分析估算法通过操作数量度量算法效率
  • 判断一个算法效率时只需要关注最高阶项就能得出结论

注意:某个算法,随着问题规模 n 的增大,它会越来越优越于另一算法,或者越来越差于另一算法。

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧