时间复杂度与空间复杂度
目录
- 算法性能分析
- 时间复杂度度量
- 空间复杂度度量
- 时间复杂度渐进分析
- 空间复杂度渐进分析
算法性能分析
数据结构的优劣与算法直接有关,针对一个具体的问题可能提出若干种不同的算法实现。如何从这些算法种找出性能最优的那个?一个算法与运行环境有关,但是运行环境大有不同,所以算法效率最好通过比较算法的复杂性的度量来评价算法的优劣。
时间复杂度度量
算法的运行时间涉及多种运算,度量算法的运行时间,主要是统计算法的程序步数,各种语句都有相应的程序步数。
空间复杂度度量
程序的存储空间包括两部分:
- 固定部分 固定部分的空间大小与输入输出的个数多少、数值的大小均无关。其主要包括存放程序指令代码的空间,常数、简单变量、定长成分(如数组元素、结构成分、对象的数据成员等)变量所占的空间等。该部分为静态空间,只需要简单的进行统计就可以估算其空间复杂度。
- 可变部分 该部分的空间主要包括其与问题规模有关的变量所占空间、递归工作栈所用空间,以及在算法运行过程中通过new和delete命令动态使用的空间。
时间复杂度渐进分析
确定一个程序的准确步数非常困难,也不必要,多数情况只要得到估计值就够了。设程序步数为n,时间复杂度为T(n),n增大T(n)也增大。
定义:若存在函数 f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称 f(n)是T(n)的同数量级函数。记作 T(n)= O(n),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。可以理解为O就是一个估算值。
保留对函数影响最高的项,n非常大时候,后面比较小的项可以忽略,如:
T(n)=n+1 忽略常数项约等于n
T(n)=n+n^2 忽略低阶项 约等于n^2
T(n)=3n 忽略最高阶的系数约等于n
程序有几种时间复杂度(依次增大):
1.O(1) 常数阶
int n;
n=10;
cout<<n;
T(n)=3,常数1取代3,时间复杂度为O(1)
2.O(logn) 对数阶
int sum=1;
while(sum<n){
sum=sum*2;
}
T(n)怎么算呢?利用数学,sum算多少步到n,2^步数=n,所以步数=logn,时间复杂度为O(n)
3.O(n) 线性阶
for(int i=0;i<n;i++){
cout<<i;
cout<<i+1;
}
T(n)=2n,n取代2n,时间复杂度为O(n)
4.O(n^2) 平方阶
for(int i=0;i<n;i++){
cout<<i;
for(int j=0;j<n;j++){
cout<<j;
}
}
T(n)=n+n2,去掉低阶n简化为n2,时间复杂度为O(n^2)
5.O(nlogn) 线性对数阶 常用,如归并排序、插入排序
for(int m=1; m<n; m++){
i=1;
while(i<n){
i=i*2;
}
}
logn对数阶我们知道了,那么其实n倍的logn就是线性对数阶
空间复杂度渐进分析
时间复杂度不是计算程序具体步数耗时,那么空间复杂度也不是用来计算程序实际占用的空间的。问题规模趋于无穷大时,用O表示法表示。
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。记为:S(n)=O(f(n))
1.O(1) 常数阶
算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)
int i=1;
int j=1;
j++;
S(n)=3,常数1取代3,空间复杂度为O(1)
2.O(n) 线性阶
int[]m= new int[n];
for(i=1;i<=n;i++) {
j++;
}
第一行动态创建数组,数据占用的大小为n,下面虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n),空间复杂度为O(n)。