算法简介及算法分析
算法简介
算法的定义:
算法是对特定问题求解步骤的一种描述,是指令的有限序列。(所以说只要满足上述条件,即使很简单的一个循环也是算法)
算法具备5个特征:
输入
输出
有穷性
确定性
可行性
什么是好算法:
正确性
鲁棒性
简单性
抽象分级
高效性
算法分析:
高效性是评价一个算法是否是好算法的重要标准,那么我们怎么判断算法是否高效呢?有的人说,把算法用程序语言实现一下,再输入多个测试数据实际检测运行速度(时间频度)和空间开销就好了呗!这种事后统计的方法并不能准确检测,它牵扯到计算机软硬件等环境因素。所以一般采用事前分析估算的方法,渐进复杂度分析方法(渐进时间复杂度和渐进空间复杂度)。
时间复杂度
当问题规模充分大时,算法中基本语句的执行次数在渐进意义下的阶,用大O记号表示。
空间复杂度
指在算法的执行过程中,需要的辅助空间数量。
算法分析计算方法:
一般我们更注重算法的时间性能,所以这里讲解时间复杂度的计算方法。
常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
首先找出所有语句中执行次数最大的那条语句作为基本语句,计算基本语句的执行次数,取其数量级放入大O中即可。
要理解这种方法还需要明白一个定义和一个定理。
定义:
若存在两个正的常数c和n0,对于任意n>=n0,都有T(n)<=c * f(n),则称T(n)=O(f(n))。
(该定义说明了函数T(n)和f(n)具有相同的增长趋势,并且T(n)的增长至多趋同于函数f(n)的增长。)
定理:
若A(n)=amnm + am-1nm-1 + am-2nm-2 + am-3nm-3 + am-4nm-4 + … + a1n1 + a0,则A(n)=O(nm)。
例题
(转载自http://blog.csdn.net/booirror/article/details/7707551/):
【1】如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
x=91; y=100;
while(y>0) if(x>100) {x=x-10;y--;} else x++;
解答: T(n)=O(1),
这个程序看起来有点吓人,总共循环运行了1100次,但是我们看到n没有?
没。这段程序的运行是和n无关的,
就算它再循环一万年,我们也不管他,只是一个常数阶的函数
【2】当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
x=1;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
for(k=1;k<=j;k++)
x++;
该程序段中频度最大的语句是(5),内循环的执行次数虽然与问题规模n没有直接关系,但是却与外层循环的变量取值有关,而最外层循环的次数直接与n有关,因此可以从内层循环向外层分析语句(5)的执行次数: 则该程序段的时间复杂度为T(n)=O(n3/6+低次项)=O(n3)
【3】算法的时间复杂度不仅仅依赖于问题的规模,还与输入实例的初始状态有关。
在数值A[0..n-1]中查找给定值K的算法大致如下:
i=n-1;
while(i>=0&&(A[i]!=k))
i--;
return i;
此算法中的语句(3)的频度不仅与问题规模n有关,还与输入实例中A的各元素取值及K的取值有关: ①若A中没有与K相等的元素,则语句(3)的频度f(n)=n; ②若A的最后一个元素等于K,则语句(3)的频度f(n)是常数0。