度量算法的效率:时间复杂度、空间复杂度。
时间复杂度,一般情况,算法中基本操作重复执行的次数是问题规模n的一个函数f(n),算法的时间度量记做T(n)=O(f(n)),他表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称做算法的渐近时间复杂度,简称时间复杂度。
插入一个概念:语句的频度指的是该语句重复执行是次数。
我们在计算时间复杂度的时候,
先要找出算法的基本操作,并根据基本操作语句计算出其执行次数。
再找出其同数量级。。。T(n)=O(f(n)=数量级)。
例如:
[cpp] view plain copy
for(i=1; i<=n; ++i)
{
for(j=1; j<=n; ++j)
{
c[i][j]=0;//该步骤属于基本操作执行次数:n的平方次
for(k=1; k<=n; ++k)
c[i][j]+=a[i][k]*b[k][j];//该步骤属于基本操作执行次数:n的三次方次
}
}
我们可以看到,其中的基本操作语句就只有两个,一个c[i][j]=0,一个c[i][j]+=a[i][k]*b[k][j],可以知道前一个的执行次数为n^2,后一个的执行次数为n^3。所以T(n)=O(n^3)。
按数量级递增排列,常见的时间复杂度有:
常数阶O(1),对数阶O(log2n),线性阶O(n),
线性对数阶O(nlog2n),平方阶O(n^2),立方阶O(n^3),...,
k次方阶O(n^k),指数阶O(2^n)。随着问题规模n的不断增大,上诉的时间复杂度不断增大,算法的执行效率越低。
在pascal中比较容易理解,容易计算的方法是:看看有几重for循环,只有一重则时间复杂度为O(n),二重则为O(n^2),依此类推,如果有二分则为O(logn),二分例如快速幂、二分查找,如果一个for循环套一个二分,那么时间复杂度则为O(nlogn)。
对于实际计算中,我们知道,对于相同的程序,对于其运行的时间,影响的因素有很多。
1.程序的算法优劣。
2.问题的规模。
3.书写程序的语言。
4.编译程序产生的机器代码在质量。
5.机器执行指令的速度。。。等等。
空间复杂度,一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。
S(n)=O(f(n))
其中n为问题的规模,S(n)表示空间复杂度。
基本操作和原操作,估计是除循环以外的其他作,即除了for、while、do while 以外的其他语句,
N * N 的矩阵相乘,有4层 for,最里层的一个整数乘法,这个乘法就是基本操作