1、概念
算法 (Algorithm)用来描述对特定问题的求解步骤,它是指令的有限序列,其中每一条指令代表一个或多个操作
算法的概念在计算机科学领域中几乎无处不在,在各种计算机系统的实现中,算法的设计往往处于核心的位置。计算机的问世是20世纪算法是计算机科学的重要基础,就像算盘一样,人们需要为计算机编制各种各样的"口诀"即算法,才能使其工作
软件(项目) = 程序 + 文档
程序 = 数据结构 + 算法
软件(项目) = 数据结构 + 算法 + 文档
2、特征
(1)有穷性:一个算法必须总是(对任何合法的输入值)执行有穷步以后结束,且每一步都可以在有穷的时间内完成
(2)确切性:算法中每一个指令都必须有确切的含义,读者和计算机在理解时不会产生二义性
(3)可行性:一个算法是能行的,即算法中描述的操作都是可以通过执行有效次基本运算来实现
(4)输入性:一个算法有零个输入或多个输入,以刻画运算对象的初始情况
所谓0个输入,就是指算法本身给出了初始条件 int a=5;
3、描述
算法的描述形式多种多样,不同的描述形式对算法的质量有一定的影响。描述同一个算法可以采用自然语言、流程图(盒图)、伪代码以及程序设计语言等,常用的描述算法方法有如下四种:
(1)自然语言描述法
最简单的描述算法的方法是使用自然语言,用自然语言来描述算法的优点是简单且便于人们对算法的理解和阅读,缺点是不够严谨,易产生歧义。当算法比较复杂且包含很多转移分支时,用自然语言描述就不是那么直观清晰了
(2)算法框图法
使用程序流程图、盒图等算法描述工具来描述算法。其特点是简洁明了、便于理解和交流
(3)伪代码语言描述法
用上述两种方法描述的算法并不能够直接在计算机上执行。为了解决理解与执行之间的矛盾,人们常常使用一种称为伪代码语言的描述方法来对算法进行描述。伪代码语言介于高级程序设计语言和自然语言之间,它忽略高级程序设计语言中一些严格的语法规则与描述细节,因此它比程序设计语言更容易描述和被人理解,而比自然语言或算法框图更接近程序设计语言
(4)高级程序设计语言描述法
使用特定的可以直接在计算机上执行的程序描述算法。优点是不用转换直接可以编译执行,缺点是需要对特定的程序设计语言比较理解。大部分的算法最终是需要通过能够向计算机发送一系列命令的程序来实现的
4、标准
(1)正确性
算法至少应该具有输出、输出和加工处理无歧义性、能正确反映问题的需求、能够得到问题的正确答案
(2)可读性
便于阅读、理解和交流
(3)健壮性
当输入数据不合法时,算法也能做出相关处理,而不是产生异常或莫名其妙的结果
(4)时间效率高与低存储量需求
时间效率指算法的执行时间,存储量主要指算法程序运行时所占用的内存或外部硬盘空间。设计算法应该尽量本着时间效率高和存储量低的要求
5、时间复杂度
对于一个算法的复杂性分析主要是对算法效率的分析,包括衡量其运行速度的时间效率,以及其运行时所需要占用的空间大小。对于算法的时间效率的计算,通常是抛开与计算机硬件、软件有关的因素,仅考虑实现该算法的高级语言程序。
算法的时间复杂度是一个函数,它定性描述该算法的运行时间,时间复杂度常用O表述,它衡量着一个程序的好坏,时间复杂度的估算是算法题的重中之重
(1)概念
要想计算时间复杂度首先得找到该算法中的循环,算法中循环执行的次数就是算法的时间复杂度
通常时间复杂度用一个问题规模函数来表达:T(n) = O(f(n))
①T(n)问题规模的时间函数
②n代表的是问题的规模输入数据量的大小
③O时间数量级
④f(n)算法中可执行语句重复执行的次数
(2)计算
函数的时间复杂度
循环的次数,是一个常数 O(1)
循环的次数,是一个n的一次幂 O(n)
循环的次数,是一个n的两次幂 O(n^2)
例题:求下面函数的时间复杂度
void func(){
int num = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
num++; // 两层循环,每次循环n次,因此为n*n
}
}
for (int k = 0; k < N; k++) {
++num; // 一层循环, 循环n次
}
for (int l = 0; l < 10; l++) {
++num; // 一层循环,循环10次
}
}
分析:
由注释,我们可以计算出时间的复杂度的表达式:N*N+N+10,但是我们能写成O(N*N+N+10)吗?
不能,我们知道对于时间复杂度,不需要算出精确的数字,只需要算出这个给算法属于什么量级即可,那么我们又如何知道它属于什么量级呢?
即:我们将字母取无穷大,例如本题中的字母为N,N取无穷大,而10对于N取无穷大后没有影响,因此10可以舍去,原表达式化为N*N+ N,再转化为N*(N+1),由于N为无穷大,因此N+1,也是没有影响的,原式就变成了O(N*N),也即O(N2),这就是大无穷(O)渐进表示法,只是一种量级的估算,而不是准确的值