在开头还是得套路一下:
所谓程序,就是数据结构加上算法,在现代的程序设计中还加上设计方法,语言工具和环境。其中,算法是指对操作的描述,未解决一个问题而采取的方法和步骤。就像一首歌的乐谱,一道菜的菜谱。
而算法复杂性是指我们设计出的算法,它在运行时所需要的计算机资源的量,在这其中,我们需要的时间资源的量称为时间复杂性,需要的空间资源的量称为空间复杂性。
在复杂性中,可分为三种情况:
平均情况:用表示
最坏情况:用大表示
最好情况:用表示
关于复杂性的表示方式,我们一般采用:
这几种表示方式。
对于这几个符号的意思,为了方便理解,我们可以假设存在两个
函数:f(n),g(n)。
(1)对于大O符号: 若存在一个自然数n 和一个常数c>0,使得,我们称f(n)的复杂性为O(g(n))的
什么意思呢?如:
f(n)=8n, g(n)=10n;
在n>=1时,有8n<=10n,即f没有g的某个常数倍增长得快(上界)故f(n)的复杂性为O(5n),又因为在复杂性表示时,其复杂程度取决于n的规模,当n很大时,数字5变变得没什么意义了所以一般省略数字,只取O(n)。
用极限表示:
( 2 )对于,若存在一个自然数n和一个常数C > 0,使得
,则称f(n)的复杂性为
(g(n))。
它跟大O是相反的,O求的是最坏情况,它求的是最好情况,对应的是算法复杂度的 下界。
用极限表示:
(3)对于符号,若存在一个自然数n和一个常数c1和c2,使得,
,则称f(n)为
的。
给出了算法运行时间增长率的一个精确描述,
f(n)=当且仅当
并且
,为什么呢?
因为大O表示法要求小于c2*g(n),而
则要求
大于c1*g(n),这样一来,因为
又要介于两者之间,所以就有上面的等式了。
( 4 )对于小O表示法,它和大O表示法的区别在于,小O要求的是严格小于c*g(n),
即,这里不再是小于等于。
这个等式表明了,当n充分大时,f对于g可以忽略不计了。
对于一个算法,我们一般分析的是最坏情况,即大O表示法,因为只要最坏的情况满足了,其他肯定也是满足的。
下面给出基本的运算规则:
对于第一条,比如:
,我们可记为O(n^2),因为n很大时,相对于n^2,20n是可以忽略的。在我们的程序设计中就像一个for循环,它的终止条件设为n,
int i=0;
for(int k=1;k<n;k++){
i++
}
我们可称这个循环的运行时间为O(n)的。
2.第二条,就像两个嵌套的for循环,像这样,我们说这两个循环的运行时间为O(mn)
int i=0;
for(int r=1;r<m;r++){
for(int i=1;i<n;i++){
i++;
}
}
3.第三条,其实就是两个并行的for,像这样,他们的运行时间为O(max(n,m))
for(int k=1;k<n;k++){
i++
}
for(int k=1;k<m;k++){
i++
}
4.对于第四条来说,其实就是一个常数乘上一个数据规模n就像在一个for循环的终止条件n上乘以一个常数,这样我们用大O来表示它最坏情况时,仍然可以写成O(n)。
5.第五条,如果g(n)函数的运行时间为O(f)那么g(n)+f(n),我们仍然可以将它当做两个并行的for循环一样,这样就像第三条,这样它的运行时间还是为O(f)。
二.
空间复杂度的计算和时间复杂类似,但是它的计算更为简单,因为它只需计算临时占用的存储空间的大小,意思就是说只考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。像我们的插入排序,虽然它的时间复杂度为O(n^2),但空间复杂度只为O(1),因为它只需要一个局部变量。
后面会对具体的排序进行复杂度的分析,各种排序算法通过下面衔接查找。
三种简单排序:点击打开链接
希尔排序:点击打开链接
快速排序:点击打开链接