算法的复杂度

 

前言:本人并非所谓的大佬,蒟蒻一枚,写文章的目的主要就是这么几个。一个是为了总结昨天学习的知识,巩固于心;二是将所学的整理起来,也方便以后备用查阅;第三个是可以给其他的有需要的人看,也可以一起学习进步,有必要还可以提建议!总之比没写强吧!缸巴咧!

评判一个程序的好坏通常有几个标准,按照程序的运行效率和代码的可读性以及代码的美观性几个方面看,而最主要的方面不过效率和可读性。可读性没什么好说了,作为团队中的那一个蒟蒻,当然没啥高深的算法描述了。最后就看效率了,效率上可分为运行时间和所需空间大小两个方面入手,数据结构上可专业的称为算法的时间复杂度和空间复杂度。接下来就进入重点了,如何评测一个程序的时间和空间复杂度?


时间复杂度

这里又引入一个专业词:时间开销T,通俗点讲就是所花的时间;问题规模n,可以看作是代码基本语句的执行数量(可以被重复执行)。很显然,时间开销和问题规模n有关,记作T(n)。

(1) T(n) = 3n + 3 -> o(f(n)) = n ,[f(n)的高阶无穷小,即n趋于无穷是等于它]
(2) T(n) = n^3 + n +9990 -> o(f(n)) = n^3 [同理趋于无穷接近]

上述式子,省略了常数,那意味着当问题规模很大时,只需要计算一些循环的基本语句的执行次数就行了。

加法

当(1)与(2)式相加时,效果还是一样,求出其高阶无穷小,简单方法就是去掉低阶项,保留高阶项。

乘法

既然都相乘了,就不好意思去掉其中任意一个了,所以吧两个高阶无穷小相乘即可。

void test(int k[],int n){   //n为数组长度
printf("I am Tiga ");
for(int i=0;i<n;i++){
if(k[i]==n){
printf("I am light %d ",n);
break;
}
}
}

就源码分析来看,入口的参数有两个,一个数组k[ ],一个整数n。而这个函数的作用在于判断数组k[ ]中是否有整数n,如果有则输出并结束。然而它的时间复杂度不是唯一确定的,需要分情况。最好情况是,数组第一个就是n,那很快就结束了,执行基本语句量为常数,记为T(n) = o(1);最坏情况是,需要找到最后一个n,根据上面的结论可得出,T(n) = o(n),进而可以求平均时间复杂度。

空间复杂度

空间复杂度就相对理解起来更容易些,因为空间复杂度很少受问题规模的影响。

void test(int n){
int k = 3;
if(k==n){
printf("Yes,Thanks! ");
}
}

上述代码几乎可以算出所需内存空间大小,如果int整形为4个字节,那么总共需要8个字节,则可以表达为S(n) =o(1),即常数级大小,那么这样典型的不受问题规模影响的空间复杂度情况就称作算法原地工作。如果受问题规模影响也能举出例子:

void test(int n){
int k[n];
k[0] = 1;
printf("Yes,Thanks %d! ",k[0]);
}

这个例子就简单又生动了,问题规模影响了空间复杂度,使它不唯一,则可以表示为S(n)= o(n)。


总结:

算法复杂度这两个方面就写完了,其实也并不复杂,复杂的还在后面。至少了解了一下算法好坏的判断标准,有助于以后写出更好的程序:执行时间少,占用空间小,效率高,美观,可读性好的程序!这就是算法的魅力所在!

我是小码,一个会发光的准程序员!欢迎大家关注我的公众号:小码之光

github:github.com/coderxm/blog

 

原文地址:https://www.cnblogs.com/coderma/p/13266102.html