第1章 算法概述
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第1章算法概述
●理解算法的概念。
●理解什么是程序,程序与算法的区别和内在联系。
●掌握算法的计算复杂性概念。
●掌握算法渐近复杂性的数学表述。
●掌握用C++语言描述算法的方法。
1.1算法与程序
1.1.1 算法(Algorithm)
算法是指解决问题的一种方法或一个过程。
算法是若干指令的有穷序列,满足性质:
①输入(Input):一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0
个输入是指算法本身定出了初始条件。
②输出(Output):一个算法有一个或多个输出,以反映对输入数据加工后的结果,
没有输出的算法是毫无意义的。
③确定性(Definiteness):组成算法的每条指令是清晰,无歧义的。
④有限性(Finiteness):算法中每条指令的执行次数是有限的,执行每条指令的时
间也是有限的。
⑤可行性(Effectiveness):算法中执行的任何计算步都是可以被分解为基本的可执行
的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)。
1.1.2 程序(Program)
●程序是算法用某种程序设计语言的具体实现。
●程序可以不满足算法的性质(4)。
●例如操作系统,是一个在无限循环中执行的程序,因而不是一个算法。
●操作系统的各种任务可看成是单独的问题,每一个问题由操作系统中的
一个子程序通过特定的算法来实现。该子程序得到输出结果后便终止。
1.1.3 问题求解(Problem Solving)
●例:编写判断存放在单链表L中的字符串是否为回文的函数。
存放字符串的单链表L的长度已知,L的示意图如下:
算法:
①定义一个栈(栈的元素类型为char ),并初始化;(SqStack S; initStack(S);)
②将单链表存储的字符串中的前一半字符进栈;
③将栈中的字符逐个与单链表中后半部分的字符进行比较,如果字符全部相等,则判断字符串是回文,如果有一个字符不相等,则判断不是回文。
bool HuiWen(LinkList L,int n){
int i=1;
SqStack s;
initStack(s);
LinkList p=L->next;
while(i<=(n/2)){
push(S,p->data);
p=p->next;
i++;
}
if((n%2)==1)
p=p->next;
while(p!=NULL){
if(pop(S)==p->data)
p=p->next;
else
return false;
}
return true;
}
1.2 算法复杂性分析
算法复杂性 = 算法所需要的计算机资源
算法的时间复杂性T(n);
算法的空间复杂性S(n)。
其中n 是问题的规模(输入大小)。
1.2.1 算法的时间复杂性
算法的时间复杂性应该集中反映算法的时间效率,并从算法的实际计算机中抽象出来。这个量应该只依赖于要解的问题的规模(N )、算法的输入(I )和算法本身(A )。 算法的时间复杂性可表示为如下的三元函数:T=T(N, I, A)
由于A 隐含于函数名当中,T 可简化为:T=T(N, I)
根据T(N, I)的概念,它应该是算法在一台抽象的计算机上运行所需的时间。
设此抽象计算机所提供的元运算有k 种,分别为O 1, O 2, …, O k ,又设每执行一次这些运算的时间分别为t 1, t 2, …, t k 。
对于给定的算法A ,用到元运算O i 的次数为e i ,显然e i 为N 和I 的函数,因此有:
一般我们只讨论三种情况下的时间复杂性,即最坏情况、最好情况和平均情况
()()∑
==k i i i I N e t I N T 1
,,
下的时间复杂性。
⑴最坏情况下的时间复杂性
⑵最好情况下的时间复杂性
⑶平均情况下的时间复杂性
可操作性最好且最有实际价值的是最坏情况下的时间复杂性。
1.2.2 算法的渐近复杂性
在评估一个算法的性能时,并不需对算法的执行时间作出准确的统计。因为我们在分析算法的性能,或把两个算法的性能进行比较时,对时间的估计是相对的,而不是绝对的。由此我们引入算法渐近复杂性的概念。
● 定义1.1 设算法的执行时间为T(N),如果存在T*(N),使得:
就称T*(N)为算法的渐近时间复杂性。
● 在数学上, T*(N)是T(N)的渐近表达式,是T(N)略去低阶项留下的主项,它比T(n) 简单。我们用T*(N)来替代T(N)作为算法在N→∞时的复杂性的度量,并作出如下进一步的简化:
– 只关心T*(N)的阶,不考虑它的常数因子;
– 假设算法中用到的所有不同的元运算各执行一次所需要的时间都是一个单位时间。
● 注意:采用渐近复杂性来衡量效率的方法得出的不是时间量,而是一种增长趋势的度量。
在算法分析中,经常遇到如下类型的复杂性,它们的阶分别是:
1 常数级
logn 对数级
n 线性级
n c 多项式级,c 为常数
c n 指数级
n! 阶乘级
例:假设某算法在输入规模为n 时的计算时间为T(n)=3×2n 。在某台计算机上实现算法的时间为t 秒。现有另一台计算机,其运行速度为第一台的64倍,那么在这台新机器上用同一算法在t 秒内能解输入规模为多大的问题?
前面给出了简化算法复杂性分析的方法和步骤,即只要考察当问题的规模充分 大时,算法复杂性在渐近意义下的阶。与此简化的复杂性分析相配套,需要引入以下渐近意义下的记号O 、Ω、θ和o 。在下面的讨论中,对所有n ,f(n)≥0,g(n) ≥0
⑴ 渐近上界记号O
定义1.2 如果存在正的常数C 和自然数N 0,使得当N≥N 0时有f(N)≤Cg(N),则称函数f(N)当N 充分大时上有界,且g(N)是它的一个上界,记为f(N)=O(g(N))。大O 符号用来描述增长率的上限,表示f(N)的增长最多像g(N)增长的那样快。这个上界的阶越低,结果就越有价值。
● 按照大O 的定义,容易证明它有如下运算规则:
● O(f(n))+O(g(n)) = O(max{f(n),g(n)})
● O(f(n))+O(g(n)) = O(f(n)+g(n))
● O(f(n))*O(g(n)) = O(f(n)*g(n)) ()()0)
(lim *=-∞→N T N T N T n