算法是对特定问题求解步骤的一种描述,是指令的有限序列,其中每条指令表示一个或多个操作。
一、特性:
一个算法还具有如下5个重要特性:1.有穷性:一个算法必然是可以自结束(不考虑外部影响)的。必然是可以执行有穷个步骤后结束,并且,每一个步骤都可在有穷时间内完成。2.确定性:无二义性,一条指令必须有一种确切的含义。3.可行性:算法中描述的操作,都是可以通过已经实现的基本运算执行有限次来实现。4.输入5.输出
二、目标:
一个合理的算法,应尽量达到这样几个目标:
1.正确性
2.可读性
3.健壮性
4.高效率与低存储量
三、度量
一个算法是由控制结构(顺序、分支、循环)和原操作构成的,则算法时间取决于两者的综合效果。算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的的时间来度量。而度量一个程序的执行时间通常有两种方法。
(1)事后统计
缺陷:a.必须先运行依据算法编制的程序;b.所得时间的统计量依赖于计算机的硬件、软件等环境因素。
(2)事前分析估算缺陷
缺陷:只作统计性分析,无统计性数据,不能真正确定算法间出现分差时的问题规模阀值;
算法分析的目的,在于选择合适的算法或改进算法来解决问题提供理论上的依据。由于,一个程序语言编写的程序,在计算机上运行时所消耗的时间受硬件、语言、程序规模等影响,采用事后统计法,通过绝对的时间单位衡量算法的效率是不合适的。因此,为了便于比较同一问题的不同算法,通常的做法是,采用事前分析估算,从算法中选取一种对于所研究的问题来说是基本操作的原操作,以该基本操作重复执行的次数作为算法的时间量度。事前的分析估算,主要从时间复杂度和空间复杂度来考量。
3.1时间复杂度:
一般情况下,算法中基本操作重复执行的次数可以用某一个关于问题规模n的函数f(n)来表达,算法的时间量度记作T(n) = O( f(n) ),它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度(asymptotic time complexity),简称为时间复杂度。按数量级递增排列,常见的时间复杂度有:
常数阶O(1),对数阶O(log2n),线性阶O(n);
线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),...;
k次方阶O(nk),指数阶O(2n)。
典型算法表达:
3.1.1常数阶O(1):
int a = 0;
int b = 1;
int c = a + b;
3.1.2对数阶O(log2n):int i = 1;
int result = 0;
while(i < n)
{
++result;
i = i * 2;
}
3.1.3线性阶O(n):
int i = 1;
int result = 0;
while(i < n)
{
++result;
++i;
}
3.1.4线性对数阶:
int i = 1;
int result = 0;
for(int j = 0; j < n; ++j)
{
while(i < n )
{
++result;
i = i * 2;
}
}
3.1.5平方阶O(n2):
int result = 0;
for(int j = 0; j < n; ++j)
{
int i = 1;
while(i < n)
{
++result;
++i;
}
}
3.1.6指数阶
指数阶时间算法通常来源于需要求出所有可能结果,多见于穷举法。例如,n个元 素的集合共有2n个子集,所以要求出所有子集的算法将是O(2n)的。
以上表达,其中,对数阶O(log2n)比较常见,很多优秀、常用的算法,都会体现出O(log2n)或是O(nlog2n),因此,此处列出对数运算的相关规则及性质如下:
若a^n=b(a>0且a≠1) ,则n=log(a)(b) ;
基本性质:
1、a^(log(a)(b))=b
2、log(a)(a^b)=b
3、log(a)(MN)=log(a)(M)+log(a)(N);
4、log(a)(M÷N)=log(a)(M)-log(a)(N);
5、log(a)(M^n)=nlog(a)(M)
6、log(a^n)M=log(a)(M)/n
3.2空间复杂度:
空间复杂度(space complexity)指算法在计算机内执行时所需存储空间的度量。用S(n) = O( f(n) ) 表示。通常考量算法的空间复杂度时,讨论的是除正常占用存开销外的辅助存储单元规模。
3.3其他考量因素:
针对算法的用途和适用环境,会适当调节T(n)与S(n)在算法选取过程中的权重。此外,某些特殊用途的算法,会适当引进其他考量因素。例如,对于排序算法,根据需要,会引入稳定度的考量。所谓稳定度,是指稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序。也就是一个排序算法是稳定的,就是当有两个有相等关键的纪录R和S,且在原本的串列中R出现在S之前,在排序过的串列中R也将会是在S之前。