算法性能分析
算法是对特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中每个指令表示一个或多个操作。
算法特性:
- 有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
- 确定性:算法中的每一条指令必须要有确定的含义,没有二义性,在任何条件下,只有唯一的一条执行路径,即对于相同的输入只能得到相同的输出。
- 可行性:算法是可执行的,算法描述的操作可以通过已经实现的基本操作执行有限次来实现。
- 输入:一个算法有零个或多个输入。
- 输出:一个算法有一个或多个输出。
算法设计要求:
- 正确性
- 可读性
- 健壮性
- 高效性
算法效率:
- 时间效率:指的是算法所耗费的时间
- 空间效率:指的是算法执行过程中所耗费的存储空间。
- 注意:时间效率和空间效率有时候是矛盾的。
时间复杂度的渐进表示法
-
为了便于比较不同算法的时间效率,我们仅仅比较他们的数量级。
例如:两个不同的算法,时间消耗分别是:T1(n)=10n² 与T2(n)=5n³,显然T1时间效率要比T2的高。所以如果选择会选择T1算法
-
若有某个辅助函数f(n),使得当n趋近与无穷大时,T(n)/f(n)的极限值为不等于0的常数,则称f(n)是T(n)的同数量级函数。记作:T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度(O是数量级符号),简称时间复杂度。f(n)就是算法中执行次数最多的语句的执行次数,n为问题规模
-
排序:n为排序数据量,矩阵:n为矩阵的阶数,多项式:n为多项式的项数,集合:n为元素个数,树:n为树的结点个数,图:n为图的顶点数或边数
时间复杂度的计算
基本方法:
-
找出语句频度最大的那条语句作为基本语句
-
计算基本语句的频度得到问题规模问题n的某个函数f(n)(级数求和的方式)
-
取其数量级用符号"O"表示
-
例题:
for(int i=1;i<=n;i++){ for(int j=1;j<=i;j++){ for(int k=1;k<=j;k++){ x=x+1; } } }
语句频度 = ∑ i = 1 n ∑ j = 1 i ∑ k = 1 j 1 语句频度=\sum_{i=1}^{n}{\sum_{j=1}^{i}{\sum_{k=1}^{j}{1}}} 语句频度=i=1∑nj=1∑ik=1∑j1
-
算法时间复杂度比较:
常数阶
O(1)<对数阶
O(logn)<线性阶
O(n)<线性对数阶
O(nlogn)<平方阶
O(n2)<k方阶
O(nk)<指数阶
O(2n)<阶乘阶
O(n!) k>2 -
对于复杂的算法,可以将它分为几个容易估算的部分,然后利用大O加法法则和乘法法则,计算算法的时间复杂度
- 加法法则:
T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))
- 乘法法则:
T(n)=T1(n)*T2(n)=O(f(n))*O(g(n))=O(f(n)*g(n))
- 加法法则:
例题:若f(n)=amnm+am-1nm-1+…+a1n+a0是m次多项式,忽略所有低次幂项和最高次幂项的系数,体现出增长率的含义,则T(n)=O(nm).
递归算法时间复杂度计算:
- 递归算法时间复杂度等于每次递归的时间复杂度*递归总次数(递归树的总节点数)
空间复杂度的渐进表示法
-
空间复杂度:算法所需存储空间的度量,记作:
S(n)=O(f(n))
,其中n为问题的规模(或大小) -
算法要占据的空间
- 算法本身要占据的空间,输入/输出,指令,常数,变量等
- 算法要使用的辅助空间(临时存储空间)
-
例题:
【算法1】 for(i=0;i<n/2;i++){ t=a[i]; a[i]=a[n-i-1]; a[n-i-1]=t; } S(n)=O(1),就一个t是临时存储空间变量 【算法2】 for(i=0;i<n;i++){ b[i]=a[n-i-1]; } for(i=0;i<n;i++){ a[i]=b[i]; } S(n)=O(n),因为a数组有多少元素,则临时存储空间b数组也需要多少元素,则空间复杂度应该就与n有关
尾言
完整版笔记也就是数据结构与算法专栏完整版可到我的博客进行查看,或者在github库中自取(包含源代码)
- 博客1: codebooks.xyz
- 博客2:moonfordream.github.io
- github项目地址:Data-Structure-and-Algorithms