算法:
1. 算法是特定问题求解步骤的描述
2. 在计算机中表现为指令的有限序列
3. 算法是独立存在的一种解决问题的方法和思想
4. 对于算法而言,语言并不重要,重要的是思想
算法与数据结构:
1. 数据结构静态的描述了数据元素之间的关系
2. 算法为了解决问题而存在
3. 数据结构是算法处理问题的载体
4. 数据结构与算法相辅相成,共同解决问题
5. 高效的程序需要在数据结构的基础上设计和选择算法
6. 高效的程序= 恰当的数据结构+ 合适的算法
算法的特性:
1. 输入:算法具有0个或多个输入
2. 输出:算法至少有1个或多个输出
3. 有穷性:算法在执行有限的步骤之后会自动结束而不会出现无限循环(算法最好在可接收的时间内完成)
4. 确定性:算法的每一步都具有确定的含义,不会出现二义性
5. 可行性:算法的每一步都必须是可行的
算法设计的要求:
1. 正确性
1) 算法对于合法数据能够得到满足要求的结果
2) 算法能够处理非法输入,并能得到合理的结果
3) 算法对于边界数据和压力数据都能得到满足要求的结果
正确性是算法最需要满足的基本准则,但是作为计算机程序,不可能无限制的满足这条准则
2. 可读性
算法要方便阅读、理解和交流
3. 健壮性(鲁棒性)
算法能够在输入数据不合法时做出相关处理,而不是产生异常或是莫名其妙的结果
4. 性价比
利用最少的资源(时间、存储空间)得到满足要求的结果
算法效率的度量:
事后统计法:
比较不同算法对同一组输入数据的运行处理时间
缺陷:
1. 必须依据算法事先编写代码
2. 运行时间严重依赖硬件及运行时的环境因素
3. 算法的测试数据选取困难,且程序的运行时间常与测试数据的规模相关
事前分析估算法:
编写代码前依据统计方法对算法进行估算
影响算法效率的主要因素:
1. 算法采用的策略、方法
2. 问题的输入规模
3. 编译产生的代码质量
4. 计算机执行速度
运行时间判定标准
测定运行时间最可靠的方法是计算能消耗运行时间的基本操作的执行次数
在分析一个算法的运行时间时,将基本操作的数量表示为输入规模的函数:
如,一段代码1+2+…..+n需要运行n次,其输入规模为n,表示f(n) = n;
函数的渐近增长:
给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有的n > N, f(n)总是比g(n)大,那么,f(n)的增长渐近快于g(n)
判断算法的效率:
忽略函数中的常数(包括加法常数、与最高阶乘法常数)以及其他次要项,关注主项(最高阶项)的阶数
某个算法,随着n的增大,它会越来越优于另一算法,或是越来越差于另一算法
注:渐进增长低的效率更高
算法的复杂度:
时间复杂度:
算法运行后对时间需求量的定性描述
空间复杂度
算法运行后对空间需求量的定性描述
时间复杂度:
1. 算法效率严重依赖于操作(Operation)的数量
2. 操作数量的估算可以作为时间复杂度的估算
3. 存在常数阶O(1)、线性阶O(n)、平方阶O(n²)
4. 表示为O(f(n)),其中f(n)是问题规模n的某个函数,即基本操作数量
计算时间复杂度
1. 用常数1取代所有加法常数
2. 只保留最高阶项
3. 如果存在与最高阶项相乘的常数,去掉这个常数
常数阶
算法执行时间恒定,与问题输入规模(n大小)无关,这种算法无论执行几次都具有O(1)时间复杂度
线性阶
线性阶时间复杂度为O(n)
for( i=0; i<n; i++ )
{
/*时间复杂度为O(1)的程序语句*/
}
//循环n次
对数阶
对数阶时间复杂度为O(logn)
int count = 1;
while( count<n )
{
/*时间复杂度为O(1)的程序语句*/
count= count * 2;
}
//循环log₂N次
平方阶
平方阶时间复杂度为O(n²)
for( i=0; i<n; i++ )
{
for( j=0; j<n; j++ )
{
/*时间复杂度为O(1)的程序语句*/
}
}
//循环n²次
常见的时间复杂度:
算法执行次数的函数 |
大O阶 |
非正式术语 |
12 |
O(1) |
常数阶 |
2n+3 |
O(n) |
线性阶 |
3n2+2n+1 |
O(n2) |
平方阶 |
5log₂n+20 |
O(logn) |
对数阶 |
2n+3nlog₂n+19 |
O(nlogn) |
nlogn阶 |
6n3+2n2+3n+4 |
O(n3) |
立方阶 |
2n |
o(2n) |
指数阶 |
时间复杂度从小到大为(越小越好)
O(1) < O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(2n) < O(n!) < O(nn)
最坏复杂度与平均复杂度
1. 最坏时间复杂度是应用运行的保证,而平均时间复杂度则是最有意义的,因为它是期望的运行时间。
2. 在没有说明的情况下,时间复杂度都指最坏时间复杂度