做了几年程序,感觉基本的东西很多还不熟悉,所以重新补充数据结构知识。
上学的时候就学习了大O表示法表示一个算法的效率,也大概明白怎么回事,知道如果没有循环的一段程序的复杂度是常数,一层循环的复杂度是O(n),两层循环的复杂度是O(n^2)? (我用^2表示平方,同理 ^3表示立方)。但是一直对于严格的定义和用法稀里糊涂。
设一个程序的时间复杂度用一个函数 T(n) 来表示,对于一个查找算法,如下:
这个程序是将输入的数值顺序地与数组中地元素逐个比较,找出与之相等地元素。
在第一个元素就找到需要比较一次,在第二个元素找到需要比较2次,…… ,在第n个元素找到需要比较n次。对于有n个元素的数组,如果每个元素被找到的概率相等,那么查找成功的平均比较次数为:
f(n) = 1/n (n + (n-1) + (n-2) + ... + 1) = (n+1)/2 = O(n)
这就是传说中的大O函数的原始定义。
要全面分析一个算法,需要考虑算法在最坏和最好的情况下的时间代价,和在平均情况下的时间代价。对于最坏情况,采用大O表示法的一般提法(注意,这里用的是“一般提法”)是:当且仅当存在正整数c和n0,使得 T(n) <= c*f(n)对于所有的n >= n0 都成立。则称该算法的渐进时间复杂度为T(n) = O(f(n))。这个应该是高等数学里面的第一章极限里面的知识。这里f(n) = (n+1)/2, 那么c * f(n)也就是一个一次函数。就是在图象上看就是如果这个函数在c*f(n)的下面,就是复杂度为T(n) = O(f(n)),对于对数级,我们用大O记法记为O(log2N)就可以了。
T(n,m) = T1(n) + T2(n) = O ( max (f(n), g(m) )
T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))
在大O表示法里面有一个特例,如果T1(n) = O(c), c是一个与n无关的任意常数,T2(n) = O ( f(n) ) 则有
T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) ).
也就是说,在大O表示法中,任何非0正常数都属于同一数量级,记为O(1)。
有如下复杂度关系
c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n!
其中c是一个常量,如果一个算法的复杂度为c 、 log2N 、n 、 n*log2N ,那么这个算法时间效率比较高 ,如果是 2^n , 3^n ,n!,那么稍微大一些的n就会令这个算法不能动了,居于中间的几个则差强人意。
定义:如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n),它是n的某一函数 T(n)称为这一算法的“时间复杂性”。
当输入量n逐渐加大时,时间复杂性的极限情形称为算法的“渐近时间复杂性”。
我们常用大O表示法表示时间复杂性,注意它是某一个算法的时间复杂性。大O表示只是说有上界,由定义如果f(n)=O(n),那显然成立f(n)=O(n^2),它给你一个上界,但并不是上确界,但人们在表示的时候一般都习惯表示前者。此外,一个问题本身也有它的复杂性,如果某个算法的复杂性到达了这个问题复杂性的下界,那就称这样的算法是最佳算法。
“大O记法”:在这种描述中使用的基本参数是 n,即问题实例的规模,把复杂性或运行时间表达为n的函数。这里的“O”表示量级 (order),比如说“二分检索是 O(logn)的”,也就是说它需要“通过logn量级的步骤去检索一个规模为n的数组”记法 O ( f(n) )表示当 n增大时,运行时间至多将以正比于 f(n)的速度增长。
这种渐进估计对算法的理论分析和大致比较是非常有价值的,但在实践中细节也可能造成差异。例如,一个低附加代价的O(n2)算法在n较小的情况下可能比一个高附加代价的 O(nlogn)算法运行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必然工作得更快。
O(1)
Temp=i;i=j;j=temp;
以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。算法的时间复杂度为常数阶,记作T(n)=O(1)。如果算法的执行时 间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
O(n^2)
2.1. 交换i和j的内容
sum=0; (一次)
for(i=1;i<=n;i++) (n次 )
for(j=1;j<=n;j++) (n^2次 )
sum++; (n^2次 )
解:T(n)=2n^2+n+1 =O(n^2)
2.2.
for (i=1;i
y=y+1; ①
for (j=0;j<=(2*n);j++)
x++; ②
}
解: 语句1的频度是n-1
语句2的频度是(n-1)*(2n+1)=2n^2-n-1
f(n)=2n^2-n-1+(n-1)=2n^2-2
该程序的时间复杂度T(n)=O(n^2).
O(n)
2.3.
a=0;
b=1; ①
for (i=1;i<=n;i++) ②
{
s=a+b; ③
b=a; ④
a=s; ⑤
}
解: 语句1的频度:2,
语句2的频度: n,
语句3的频度: n-1,
语句4的频度:n-1,
语句5的频度:n-1,
T(n)=2+n+3(n-1)=4n-1=O(n).
算法的时间复杂度(大O表示法)2
2007-06-04 13:34
O(log2n ) |