1、算法复杂度的衡量
- 内存(Memory)
- 时间(Time)
- 指令的数量(Number of Steps)
- 特定操作的数量
- 磁盘访问数量
- 网络包数量
- 渐进复杂度(Asymptotic Complexity)
2、算法的时间复杂度
算法的时间复杂度一般分析的都是渐进复杂度,即输入的数据规模趋于无穷大
算法分析的种类
- 最坏情况(Worst Case):任意输入规模的最大运行时间。(Usually)
- 平均情况(Average Case):任意输入规模的期待运行时间。(Sometimes)
- 最佳情况(Best Case):通常最佳情况不会出现。(Bogus)
例如,在一个长度为 n 的列表中顺序搜索指定的值,则
最坏情况:n 次比较
平均情况:n/2 次比较
最佳情况:1 次比较
在实际中,我们一般仅考量算法在最坏情况下的运行情况
复杂度 | 标记 | 描述 |
---|---|---|
常量 | O(1) | 操作的数量为常数,与输入的数据的规模无关。 |
对数 | O( log2n ) | 操作的数量与输入数据的规模 n 的比例是 log2(n) |
线性 | O(n) | 操作的数量为常数,与输入的数据的规模无关。 |
平方 | O( n2 ) | 操作的数量与输入数据的规模 n 的比例为二次平方。 |
立方 | O( n3 ) | 操作的数量与输入数据的规模 n 的比例为三次平方。 |
指数 | O( kn ) | 指数级的操作,快速的增长。 |
ps: log2n = x 则: 2x = n 所以随着n的快速增长,x是缓慢增长的
一般的规则为
c <
log2n
< n <
n2
<
n3
<
2n
<
3n
< n! (c是一个常量)
|——–较好—–|—一般—|——较差——|
3、几个常见的时间复杂度进行示例说明:
3.1 O(1)
Temp=i;
i=j;
j=temp;
以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。算法的时间复杂度为常数阶,记作T(n)=O(1)。
3.2 O( log2n )
int i=1;
while (i<=n)
i*=2;
第一条频度为1
第二条频度为2^f(n)<=n 则f(n)<=
log2n
(while判断不成立要多执行一次)
第三条频度为
log2n
T(n) = 1+(
log2n
+1)+
log2n
= 2
log2n
+2 = O(
log2n
)
3.3 O(n)
int m=0;
for(int i=0;i<n;i++)
m++;
第一条频度为1
第二条i=0频度1 i<n频度为n+1 (判断不成立要多执行一次) i++为n
第三条频度为n
T(n)= 1+(1+n+1+n)+n = 3n+3 = O(n)
3.3 O(n)
sum=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
sum++;
第一条频度为1
第二条为1/n+1/n
第三条为n/n*(n+1)/n
第四条为n*n
T(n) = 1+(1+n+1+n)+(n+n*(n+1)+n)+n*n = 2
n2
+5n+3 = O(
n2
)
4、空间复杂度
一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
- 固定部分 这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
- 可变空间 这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。S(n)=O(f(n)) 其中n为问题的规模,S(n)表示空间复杂度。
参考:
http://www.cnblogs.com/gaochundong/p/complexity_of_algorithms.html
http://blog.youkuaiyun.com/zolalad/article/details/11848739