笔记-算法-复杂度
1. 算法复杂度简介
算法复杂度用于衡量某一算法在时间和存储空间上的开销;一般情况下主要讨论时间开销;
2. 时间复杂度
2.1. 时间复杂度定义
在分析算法时间开销时,语句的执行次数t(n)*单条语句执行时间=总时间;
单条语句执行时间一般设定为一个常数,而T(n)是关于问题规模n的函数,分析算法复杂度就是分析T(n)随n的变化情况并确定T(n)的数量级(在大规模事件中,数量级比具体数字重要得多)。
常用算法时间复杂度表示方法:T(n)=O(f(n))
这种方法称之为大O记法。
2.2. 推导方法
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
2.3. 常见算法时间复杂度
时间复杂度包括最坏复杂度和平均复杂度,一般情况下不特别说明,讨论的时间复杂度是最坏情况下的时间复杂度。
按数量级递增排列,常见的时间复杂度有:
常数阶 |
对数阶 |
线性阶 |
线性对数阶 |
平方阶 |
立方阶 |
…… |
K次方阶 |
指数阶 |
O(1) |
O(log2 n ) |
O(n) |
O(nlog2 n) |
O(n2 ) |
O(n3 ) |
O(nk ) |
O(2n ) |
复杂度低 ---->---->---->----> 复杂度高
随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
下面的图片更形象说明了不同阶数算法的执行效率。
3. 空间复杂度
与时间复杂度类似,空间复杂度是指算法在计算机内执行时所需存储空间的度量。记作:
S(n)=O(f(n))
算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数,与问题的规模没有关系。算法的空间复杂度S(n)定义为该算法所耗费空间的数量级。
若算法执行时所需要的辅助空间相对于输入数据量n而言是一个常数,则称这个算法的辅助空间为O(1);
递归算法的空间复杂度:递归深度N*每次递归所要的辅助空间,如果每次递归所需的辅助空间是常数,则递归的空间复杂度是 O(N).
空间复杂度的分析方法:
一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。
一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。
算法的空间复杂度一般也以数量级的形式给出。如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为O(log2n);当一个算法的空间复杂度与n成线性比例关系时,可表示为O(n)。若形参为数组,则只需要为它分配一个存储由实参传送来的一个地址指针的空间,即一个机器字长空间;若形参为引用方式,则也只需要为其分配存储一个地址的空间,用它来存储对应实参变量的地址,以便由系统自动引用实参变量。
空间复杂度补充
一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。S(n)=O(f(n)) 其中n为问题的规模,S(n)表示空间复杂度。
4. 附-时间与空间复杂度比较
对于一个算法,其时间复杂度和空间复杂度往往是相互影响的。当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间。
另外,算法的所有性能之间都存在着或多或少的相互影响。因此,当设计一个算法(特别是大型算法)时,要综合考虑算法的各项性能,算法的使用频率,算法处理的数据量的大小,算法描述语言的特性,算法运行的机器系统环境等各方面因素,才能够设计出比较好的算法。算法的时间复杂度和空间复杂度合称为算法的复杂度。
常用的算法的时间复杂度和空间复杂度:
排序法 |
平均时间 |
最差情形 |
稳定度 |
额外空间 |
备注 |
冒泡 |
O(n2 ) |
O(n2 ) |
稳定 |
O(1) |
n较小时较好 |
交换 |
O(n2 ) |
O(n2 ) |
不稳定 |
O(1) |
n较小时较好 |
选择 |
O(n2 ) |
O(n2 ) |
不稳定 |
O(1) |
n较小时较好 |
插入 |
O(n2 ) |
O(n2 ) |
稳定 |
O(1) |
大部分已排序时较好 |
基数 |
O(logR B) |
O(logR B) |
稳定 |
O(n) |
B是真数(0-9), R是基数(个十百) |
Shell |
O(nlogn) |
O(ns ) 1<s<2 |
不稳定 |
O(1) |
s是所选分组 |
快速 |
O(nlogn) |
O(n2 ) |
不稳定 |
O(nlogn) |
n较大时较好 |
归并 |
O(nlogn) |
O(nlogn) |
稳定 |
O(1) |
n较大时较好 |
堆 |
O(nlogn) |
O(nlogn) |
不稳定 |
O(1) |
n较大时较好 |
稳定的排序:保证,排序关键字相同的情况下,对象的相对位置不变