时间复杂度:一个程序运行所需要的时间为编译时间和运行时间之和,编译时间与实例特征无关。我们主要关注程序的运行时间。
估算时间复杂度的方法:操作计数
1.找出一个或者多个关键操作,确定他们的执行时间。
2.确定关键操作的步数。
因为计算一个程序所有的步数和执行时间不现实,所以我们一般找出最耗费时间的几个关键操作,
然后计算这几个操作的步数,然后估算程序的步数。
程序步:一个语法或语义上的程序片段,该片段的执行时间独立于实例特征。
我们定义关键操作时,可以小到+,-等等原子操作,但是我们一般都是选取一个组合作为一个关键操作,这个组合就称为程序步,不如我们可以把return a+b+c*d+(a+g*f)中的后面的算法定义为一个程序步。但是程序步要求其和实例特征无关,即不管输入怎么变,我这个语句的操作时间都不固定不变的。比如2**n就不能选做程序步,因为他和输入特征n的大小有关系。
这里贴一个计算程序步的例子:
template<class T>
T sum(T a[],int n)
{
T theSum=0;
stepCount++;//上一句初始化作为一个程序步
for(int i=0;i<n;i++)
{
stepCount++;//for循环的每一次条件判断为一个程序步
theSum+=a[i];
stepCount++;//上一句的加法作为一个程序步
}
stepCount++;//for循环的最后一次条件判断作为一个程序步。
stepCount++;//return作为一个程序步。
return theSum;
}
操作计数主要计算关键操作的时间,并不精确,所以我们要非常谨慎的使用它。
我们更长使用的是总的步数,但是总的步数太多也不可能计算的太精确,可能不同的人的计算都不相同,所以对于总步数,我们
通常采用渐进计法即仅计算其最高阶次,比如2*n^2+2*n+c渐进计法认为该复杂度为O(n^2).