复杂度
纲要:
算法效率 时间复杂度 概念 大O的渐进表达 示例 空间复杂度 概念 示例
在我们学习了C语言之后,我们会跳到更高的地方,所以今天,我们来到了数据结构。
下面,数据结构的大门将正式打开!
一.算法效率 算法效率分析分为两种:
1.时间效率
时间效率又称时间复杂性,主要衡量算法的运行速度。
2.空间效率
空间效率也被称为空间复杂性,它主要测量算法所需的额外空间。在计算机发展的早期阶段,由于技术水平有限,计算机容量往往很小,但随着技术的快速发展,计算机的存储容量已经达到了很高的水平。所以我们现在不需要特别关注算法的空间复杂性。
二.时间复杂度 1.概念
算法的时间复杂性是计算机科学中的一个函数,它定量地描述了算法的运行时间。一 从理论上讲,算法执行所花费的时间是无法计算的。只有把程序放在机器上,你才能知道。但是我们需要在机器上测试每个算法吗?可以在机器上进行测试,但同一算法在不同性能的机器上会有不同的差异,因此有时间复杂性的分析方法。
由于算法所花费的时间与句子的执行次数成正比,算法中基本操作的执行次数是算法的时间复杂性。
例如,以下代码的执行次数是多少?
复制代码 #include <stdio.h>
void Func1(int N) { int count = 0; for (int i = 0; i < N ; i) { for (int j = 0; j < N ; j) { count; } } for (int k = 0; k < 2 * N ; k) { count; } int M = 10; while (M–) { count; } printf("%d\n", count); } 复制代码 显然,它的执行次数为 F=NN 2N 10;
当我们计算时间的复杂性时,我们通常会写一个概数。为什么?
让我们想象一下,当N上述执行次数函数,当N趋于无限时,这10对它的影响很小。如果它是一个高级函数,这个函数的大小通常取决于表达式中最高次数,所以我们的时间复杂性也采用了这个想法。
让我们来测试一下:
复制代码 #include <stdio.h> #include <time.h>
void Func1(int N) { int start = clock(); int count = 0; for (int i = 0; i < N ; i) { for (int j = 0; j < N ; j) { count; } } for (int k = 0; k < 2 * N ; k) { count; } int M = 10; while (M–) { count; } int end = clock(); printf("%d\n", end - start);//单位为毫秒 }
int main() { Func1(0);//0 Func1(100);//0 Func1(10000);//386 return 0; } 复制代码 我们发现差异主要在最高水平。所以接下来我们来介绍一下大O的渐进表达。
2.大O渐进表达法
事实上,当我们计算时间的复杂性时,我们不需要计算准确的执行次数,只需要大致的执行次数,所以我们在这里使用大O的渐进表达。
大O符号(Big O notation):是用来描述函数渐进行为的数学符号。
推广大O阶法:
用常数1代替运行时间中的所有加法常数。
在修改后的运行次数函数中,只保留最高阶项。
3.如果最高阶项存在而不是1,则删除与该项目相乘的常数。结果是大O阶。
因此,使用大O的渐进表达法后,Func时间复杂度为:O(N^2);
通过以上,我们可以得到大O的渐进表达去掉对结果影响不大的项目,简洁明了地表示执行次数。
此外,有些算法的时间复杂性最好、平均和最坏:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任何输入规模的预期运行次数
最佳情况:任意输入规模的最小运行次数(下界)
例如:
复制代码 //描述:传递一个数组,给定一个数,找出这个数组是否包含在这个数组中 int FindNum(int* arr,int N,int search_num) { int i = 0; for(i=0;i<len;i ) { if(search_num == arr[i]) return 1;//发现后返回 1 } return 0.//找不到就返回 0 } 复制代码 最好的情况是 1 ,即使只执行一次,也会发现
平均情况:N/2
最差情况: N ,整个数组遍历。
那么,这个算法的时间复杂性是多少呢?答案是: O(N)
在计算时间复杂性时,我们往往会得到最差的情况。
3.示例
复制代码 // 1.计算Func2的时间复杂度? void Func2(int N) { int count = 0; for (int k = 0; k < 2 * N ; k) { count; } int M = 10; while (M–) { count; } printf("%d\n", count); } 复制代码 它的时间复杂度是多少? ---- O(N)
复制代码 // 2.计算Func3时间复杂度? void Func3(int N, int M) { int count = 0; for (int k = 0; k < M; k) { count; } for (int k = 0; k < N ; k) { count; } printf("%d\n", count); } 复制代码 答案是:O(N M) ,因为在这个公式中,我们不知道M和N如果N>>M,那么这个问题的时间复杂O(N)
复制代码 //3. 计算Func4时间复杂度? void Func4(int N) { int count = 0; for (int k = 0; k < 100; k) { count; } printf("%d\n", count); } 复制代码 对于它来说,执行次数是一个确定的常数00,所以它的时间复杂度是 O(1)
复制代码 // 4.计算BubbleSort时间复杂度? void BubbleSort(int* a, int n) { assert(a); for (size_t end = n; end > 0; --end) { int exchange = 0; for (size_t i = 1; i < end; i) { if (a[i-1] > a[i]) { Swap(&a[i-1], &a[i]); exchange = 1; } } if (exchange == 0) break; } } 复制代码 对于实例4基本操作执行最好N次,最坏执行了(N*(N 1)/2次,通过推导大O阶法 时间复杂度一般最差,所以时间复杂度是 O(N^2)
复制代码 // 5.计算BinarySearch时间复杂度? int BinarySearch(int* a, int n, int x) { assert(a); int begin = 0; int end = n-1; while (begin < end) { int mid = begin + ((end-begin)>>1); if (a[mid] < x) begin = mid+1; else if (a[mid] > x) end = mid; else return mid; } return -1; } 复制代码 实例5基本操作执行最好1次,最坏O(logN)次,时间复杂度为 O(logN)(我们可以通过折纸查找的方式理解logN是怎么计算出来的)
注:
logN在算法分析中表示是底数为2,对数为N。有些地方会写成lgN。
// 6.计算阶乘递归Factorial的时间复杂度? long long Factorial(size_t N) { return N < 2 ? N : Factorial(N-1)*N; } 对于递归的时间复杂度我们怎么算呢?
递归的时间复杂度 = 递归次数*每次递归中的次数
对于上题,一共递归了N次,每次递归中只有一次,所以时间复杂度为O(N)
http://www.taom8.com http://www.hmgczx.com http://www.bizhizhigan.com http://www.quanshengbio.com http://www.0596pzh.com http://www.hlzxcy8899.cn http://www.mingyan365.cn http://www.20862.cn http://www.zqshihua.cn http://www.xuechengyikao.cn http://www.quanqiudianying.com http://www.meinanzhi.cn http://www.qizhenwei.cn http://www.1pinju.cn http://www.bxaad.com http://www.qiaolr.com http://www.120huadong.com http://www.xuqinw.com http://www.jgw765.com http://www.meaqimongl.com http://www.yyjinmeng.cn http://www.kor-doctor.cn http://www.cxsex.cn http://www.sgjmw.cn http://www.qcyhb.cn http://www.jh-xc.com http://www.anyuebei.com http://www.wannengyijia.com http://www.xinlongdakqf.com http://www.aotaijidian.com http://www.wanputi.com http://www.tiancankj.cn http://www.wcfxsh.cn http://www.gzsrjx.cn http://www.qiniupump.cn http://www.njwxeq.cn http://www.1yuanzg.cn http://www.dongzhichun.cn http://www.dongdazhai.cn http://www.dezhenbang.cn http://www.hsguosen.cn http://www.jmjtc.cn http://www.lianweikaisuo.cn http://www.fscaitian.cn http://www.whsdbg.cn http://www.bblys.cn http://www.icemonkey.com.cn http://www.szvolkin.cn http://www.haoma999.com http://www.lieshangjob.com http://www.jiniuai.com http://www.eqdiy.com http://www.junshitianxia.com http://www.baliimpression.com http://www.bdtylq.com http://www.mcvvv.com http://www.dingchenwy.com http://www.365wende.com http://www.boquanjiaju.cn http://www.flashcredit.cn http://www.huizujiapu.cn http://www.filmvideo.com.cn http://www.www868.cn http://www.fqathb.com http://www.wxxhr.com http://www.zuoshoujiwangzhan.com http://www.ychydraulic.com http://www.qxyuxin.com http://www.e-jke.com http://www.szspnet.com http://www.mingyin246.com http://www.teagk.com http://www.zzjishiyu.com http://www.dfbanjia.cn http://www.nmt180.cn http://www.njtcbj.cn http://www.ysxpj.cn http://www.xryoga.cn http://www.99-ts.com http://www.mokeculture.com http://www.wenyaqkw.com http://www.modalsukses.com http://www.neli-studios.com http://www.delight-esthe.com http://www.soumokuan.com http://www.superbike38.com http://www.drtahqiqco.com http://www.vimaxshop.com http://www.baozouweilai.com http://www.vechainicowei.com http://www.longsheng588.com http://www.bookbbs.cn http://www.jnjhcm.com http://www.xqgangting.com http://www.vunsher.com http://www.hefeiqianghui.com http://www.jyxk120.com http://www.yunnanpeixun.top http://www.aimeire.cn http://www.leadpacking.cn http://www.gaokao123.org.cn http://www.icct.org.cn http://www.selfnet.cn http://www.87716425.com http://www.cxhzyl.org.cn http://www.fnxzfw.cn http://www.fzjszjz.cn http://www.jrcn.com.cn http://www.ruizhiyuantech.cn http://www.itbooks.cn http://www.liuyanoffice.com http://www.yihaiis.com.cn http://www.sxhanhui.com http://www.youba8.com http://www.zzhyqd.com http://www.yantaizy.cn http://www.qingquxiaoyou.com http://www.yesexy.com http://www.lanqiuhuo.com http://www.fenke.cc http://www.114yiyao.com http://www.srbpf.com http://www.5cdmi.com http://www.91jhx.com http://www.eagle318.com http://www.lhglt.com http://www.xingyuesports.cn http://www.zhiliaobaidianfeng.cn http://www.light361.com http://www.xiyulieren.top http://www.startupdog.cn http://www.manyouyou.com.cn http://www.okbiz.com.cn http://www.mmphoto.cn http://www.quanbba.com http://www.xmbns.com http://www.hpyweb.com http://www.qingdaotangshi.cn http://www.dllongxiang.cn http://www.zibolan.com.cn http://www.lyrsjkx.cn http://www.rqzhly.cn http://www.hsapjx.cn http://www.bxgscc.cn http://www.yinyuewenxue.cn http://www.211idc.cn http://www.tejiavip.cn http://www.yearita.cn http://www.91buycar.cn http://www.021pc120.cn http://www.sxbyz.cn http://www.mobilegoogle.cn http://www.czshjz.cn http://www.zhichengsb.cn
//7. 计算斐波那契递归Fibonacci的时间复杂度? long long Fibonacci(size_t N) { return N < 2 ? N : Fibonacci(N-1)+Fibonacci(N-2); } 在这个例中,一共递归了N次,而在递归中的次数为2N-1,所以最后的时间复杂度为:O(N2)
注:
如果有一个递归有N层,且每一层中又有N次,那么它最后的时间复杂度为 O(N^2)
三.空间复杂度 1.概念
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少 bytes的空间,因为这个也没太大意义,
所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践 复杂度类似,也使用大O渐进表示法。(估算)
2.示例
复制代码 //1. 计算BubbleSort的空间复杂度? void BubbleSort(int* a, int n) { assert(a); for (size_t end = n; end > 0; --end) { int exchange = 0; for (size_t i = 1; i < end; ++i) { if (a[i-1] > a[i]) { Swap(&a[i-1], &a[i]); exchange = 1; } } if (exchange == 0) break; } } 复制代码 我们要注意在计算时,我们计算的是算法需要的额外空间,不考虑数组输入的空间。并且我们要注意,空间是可以复用的,比如所某个算法需要创建一个变量并不断的为这个变量赋值,这时这个空间复杂度为O(1);
所以,因实例1使用了常数个额外空间,所以空间复杂度为 O(1)
复制代码 //2. 计算生成的Fibonacci数组的空间复杂度? long long* Fibonacci(size_t n) { if(n==0) { return NULL; }
long long * fibArray =
(long long *)malloc((n+1) * sizeof(long long));
fibArray[0] = 0;//斐波那契数的第一个
fibArray[1] = 1;//斐波那契数的第二个
for (int i = 2; i <= n ; ++i)//利用循环来生成斐波那契数
{
fibArray[i ] = fibArray[ i - 1] + fibArray [i - 2];
}
return fibArray ;
} 复制代码 实例 2动态开辟了N个空间来放N个斐波那契数,所以空间复杂度为 O(N)
//3. 计算阶乘递归Factorial的空间复杂度? long long Factorial(size_t N) { return N < 2 ? N : Factorial(N-1)*N; } 递归算法的空间复杂度通常情况下为 递归的深度 (递归的次数)
实例3递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。所以空间复杂度为O(N).
那么在最后我们再来看一张图:
这就说明有时候 不同的时间复杂度在N小的时候都还接近,当N越来越大时差距越来越多!