算法分析与设计教案Word文档下载推荐.docx
《算法分析与设计教案Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《算法分析与设计教案Word文档下载推荐.docx(37页珍藏版)》请在冰豆网上搜索。
算法的复杂性越高,所需的计算机资源越多。
1.时间复杂度
一个算法的时间复杂度是指算法运行所需的时间。
一个算法的运行时间取决于算法所需执行的语句(运算)的多少。
算法的时间复杂度通常用该算法执行的总语句(运算)的数量级决定。
一条语句的数量级即执行它的频数,一个算法的数量级是指它所有语句执行频数之和。
在分析算法时,隐藏细节的数学表示方法为大写字母“O”记法,它可以帮助我们简化算法复杂度计算的许多细节,提取主要成分。
算法的执行频数的数量级直接决定算法的时间复杂度。
2.空间复杂度
算法的空间复杂度是指算法运行的存储空间,是实现算法所需的内存空间的大小。
一个程序运行所需的存储空间通常包括固定空间需求与可变空间需求两部分。
(1)固定空间需求包括程序代码、常量与静态变量等所占的空间。
(2)可变空间需求包括局部作用域非静态变量所占用的空间、从堆空间中动态分配的空间与调用函数所需的系统栈空间等。
l-3算法与程序设计
1.算法与程序
(1)计算机的一切操作都是由程序控制的,离开了程序,计算机将一事无成。
从这个意义来说,计算机的本质是程序的机器,程序是计算机的灵魂。
(2)算法是程序的核心。
程序是某一算法用计算机程序设计语言的具体实现。
一个程序应包括对数据的描述与对运算操作的描述两个方面的内容。
数据结构+算法=程序
数据结构是对数据的描述;
算法是对运算操作的描述。
2.结构化程序设计
任何简单或复杂的算法都可以由顺序结构、选择结构和循环结构这三种基本结构组合而成。
所以,顺序结构、选择结构和循环结构被称为程序设计的三种基本结构,也是结构化程序设计必须采用的结构。
结构化程序设计的基本要点:
(1)自顶向下,逐步求精
(2)模块化设计
(3)结构化编码
逐步求精总是和自顶向下结合使用,将问题求解逐步具体化的过程,一般把逐步求精看作自顶向下设计的具体体现。
模块化是结构化程序设计的重要原则。
一个程序是由一个主控模块和若干子模块组成。
主控模块用来完成某些公用操作及功能选择;
而子模块用来完成某项特定的功能。
教学过程设计
一、引言
回顾数据结构课程中的算法概念、排序算法等知识,从而引出本课程内容。
二、讲授
借助多媒体课件,讲解算法的复杂性,主要包括时间复杂性与空间复杂性。
讲解最坏情况、最好情况与平均情况的时间复杂性。
讲解算法复杂性在渐近意义下的阶,主要包括
、
与o,并通过具体例子说明。
三、课堂实践操作
让学生自己分析阶乘函数的时间复杂度与空间复杂度。
四、课堂总结
作业、讨论题、思考题
1.分数分解算法描述,把真分数a/b分解为若干个分母为整数分子为“1”的埃及分数之和;
所用教材和主要参考资料
《算法分析与设计及案例教程》师智斌2014
七月在线算法网站
实验楼
课后小结
本节课主要讲解了算法的特点与复杂性
算法分析与设计理论课程教案
第二章枚举算法
了解枚举算法的概念与枚举设计要领
应用枚举求解统计求和与求最值等基本案例
对某些枚举算法进行改进与优化
掌握枚举算法时间复杂度分析
1-1枚举概述
1.枚举的概念
(1)枚举法(Enumerate)也称为列举法、穷举法,是蛮力策略的体现,又称为蛮力法。
(2)枚举是一种简单而直接地解决问题的方法,其基本思想是逐一列举问题所涉及的所有情形。
(3)应用枚举时应注意对问题所涉及的有限种情形进行一一列举,既不能重复,又不能遗漏。
2.枚举的框架描述
n=0;
for(k=<
区间下限>
;
k<
=<
区间上限>
k++)
//控制枚举范围
if(<
约束条件>
)//根据约束条件实施筛选
{printf(<
满足要求的解>
);
//输出解
n++;
//统计解的个数
}
3.枚举的实施步骤
(1)根据问题的具体情况确定枚举量(简单变量或数组);
(2)根据问题的具体实际确定枚举范围,设置枚举循环;
(3)根据问题的具体要求确定筛选(约束)条件;
(4)设计枚举程序并运行、调试,对运行结果进行分析与讨论。
2-1案例应用
例:
指定特殊整数
试求含有数字7且不能被7整除的5位整数的个数,并求这些整数的和。
同时,求这些整数中恰含2个数字7的整数的个数,以及这些整数的和。
枚举设计要点
(1)设置k循环,循环n-1次相乘求出最小的n位整数t。
然后设置k从t至10*t-1循环,枚举所有n位整数。
(2)每个n位整数k赋给d(为了保持k不变)。
然后通过n次求余先后分离出k的数字c,并通过f(c)=f(c)+1统计数字c的个数。
例如f(7)=2,说明k中恰含2个数字7;
若f(3)>
0,说明k中含有数字3。
(3)据f(m)>
0&
&
k%m>
0检测含有数字m且不能被m整除,g1与s1作统计求和。
(4)据f(m)=2&
0检测恰含2个m且不能被m整除,g2与s2作统计求和。
解佩尔方程
佩尔(Pell)方程是关于x,y的二次不定方程
(其中n为非平方正整数)
当x=1或x=-1,y=0时,显然满足方程。
常把x,y中有一个为零的解称为平凡解。
我们要求佩尔方程的非平凡解。
设置y从1开始递增1取值,对于每一个y值,计算a=n*y*y后判别:
若a+1为某一整数x的平方,则(x,y)即为所求佩尔方程的基本解。
若a+1不是平方数,则y增1后再试,直到找到解为止。
应用以上枚举探求,如果解的位数不太大,总可以求出相应的基本解。
如果基本解太大,应用枚举无法找到基本解,可约定一个枚举上限,例如10000000。
可把y<
=10000000作为循环条件,当y>
10000000时结束循环,输出“未求出该方程的基本解!
”而结束。
回顾算法概念,提出问题,从而引出本课程内容。
借助多媒体课件,讲解枚举概念,常见案例。
让学生动手实践顺序查找问题。
1.最小连续n个合数,试求出最小的连续n个合数。
枚举思路的调整、枚举规律的归纳、枚举结构的设置与枚举参量的选择,都有一定的技巧运用,自然也存在许多改进与优化的空间。
3
第二章递推
了解递推算法的概念与各类递推设计要领
应用递推算法求解典型的数列与数阵案例
对某些实际问题设计多种递推算法
对某些递推算法进行改进与优化
1-1递推概述
1.递推的概念
(1)递推是利用问题本身所具有的递推关系求解问题的一种方法,是在命题归纳时,可以由n−k,…,n−1的情形推得n的情形。
(2)递推算法的基本思想是把一个复杂的庞大的计算过程转化为简单过程的多次重复,该算法充分利用了计算机的运算速度快和不知疲倦的特点,从头开始一步步地推出问题最终的结果。
(3)一个有规律的序列的相邻位置上的项之间通常存在着一定的关系,可以借助已知的项,利用特定的关系逐项推算出它的后继项的值,直到找到所需的那一项为止。
2.递推关系
递推算法的首要问题是得到相邻的数据项之间的关系,即递推关系。
(1)递推关系是一种高效的数学模型,是递推应用的核心。
(2)递推关系不仅在各数学分支中发挥着重要的作用,由它所体现出来的递推思想在各学科领域中更是显示出其独特的魅力。
3.递推的实施步骤
(1)确定递推变量
递推变量可以是简单变量,也可以是一维或多维数组。
(2)建立递推关系
递推关系是递推的依据,是解决递推问题的关键。
(3)确定初始(边界)条件
根据问题最简单情形的数据确定递推变量的初始(边界)值,这是递推的基础。
(4)对递推过程进行控制
递推过程控制:
递推在什么时候结束,满足什么条件结束。
4.递推算法框架描述
(1)简单顺推算法
顺推即从前往后推,从已求得的规模为1,2,…,i-1的一系列解,推出问题规模为i的解,直至得到规模为n的解:
f(1—i-1)=<
初始值>
;
//确定初始值
for(k=i;
=n;
k++)
f(k)=<
递推关系式>
//根据递推关系实施顺推
print(f(n));
//输出n规模的解f(n)
(2)简单逆推算法
逆推即从后往前推,从已求得的规模为n,n−1,…,i+1的一系列解,推出问题规模为i的解,直至得到规模为1的解:
f(n—i+1)=<
//确定初始值
k>
=1;
k--)
//实施逆推
print(f
(1));
(3)较复杂的递推问题需设置多重循环递推。
(4)多关系分级递推算法
当递推关系包含两个或两个以上关系式时,通常应用多关系分级递推算法求解。
f(1:
i-1)=<
//赋初始值
{if(<
条件1>
)
递推关系式1>
//根据关系1递推
……
条件m>
递推关系式m>
//根据关系m递推
2-1递推数列
已知递推数列:
a
(1)=1,a(2i)=a(i)+1,a(2i+1)=a(i)+a(i+1)(i为正整数)试求该数列的第n项与前n项中哪些项最大?
最大值为多少?
递推设计要点
(1)设置a数组,赋初值a
(1)=1。
(2)根据递推式,在i循环中据项序号i(2─n)为奇或偶作不同递推:
若mod(i,2)=0,a(i)=a(i/2)+1
若mod(i,2)=1,a(i)=a((i+1)/2)+a((i-1)/2)
(3)每得一项a(i),与最大值max作比较:
如果a(i)>
max,则max=a(i)。
(4)在得到最大值max后,最后在所有n项中搜索哪些项为最大项(因最大项可能多于一项),并输出最大值max及所有搜索得到的最大项。
2-2猴子爬山
一个顽猴在一座有30级台阶的小山上爬山跳跃,猴子上山一步可跳1级,或跳3级,试求上山的30级台阶有多少种不同的爬法。
设爬k级台阶的不同爬法为f(k)种。
(1)探求f(k)的递推关系。
上山最后一步到达第30级台阶,共有f(30)种不同的爬法;
到第30级之前位于哪一级呢?
无非是位于第29级(上跳1级即到),有f(29)种;
或位于第27级(上跳3级即到),有f(27)种;
于是有f(30)=f(29)+f(27)
一般地有递推关系:
f(k)=f(k-1)+f(k-3)(k>
3)
(2)确定初始条件
f
(1)=1;
即1=1
f
(2)=1;
即2=1+1
f(3)=2;
即3=1+1+1;
3=3
应用递推求解,关键在于根据问题的具体实际进行归纳与探索,寻求与确定符合实际的递推关系,这既是重点,也是难点。
回顾数据结构课程中的算法概念,提出问题,从而引出本课程内容。
借助多媒体课件,讲解递推概念,主要包括递推方式。
让学生动手实践斐波那契额数列递推过程。
1.求裴波那契数列的第40项与前40项之和的递推算法与迭代算法,写出完整的程序,并比较其运行结果。
本节课主要讲解了递推算法的应用
4
第三章递归与分治算法
了解递归算法的概念与递归设计要领
掌握应用递归算法求解排序与选择、实现排列组合等典型案例
递归关系与边界条件的探求与确定
递归的理解
1-1递归概述
1.递归的概念
递归就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。
递归有两个基本要素:
⑴边界条件:
确定递归到何时终止;
⑵递归模式:
大问题是如何分解为小问题的,确定递归体。
2.递归方法基本步骤
(1)根据实际构建递归关系
(2)确定递归边界
(3)编写递归函数
(4)设计主函数调用递归函数3.递推的实施步骤
3.递归函数的运行轨迹
在递归函数中,调用函数和被调用函数是同一个函数,需要注意的是递归函数的调用层次,如果把调用递归函数的主函数称为第0层,进入函数后,首次递归调用自身称为第1层调用;
从第i层递归调用自身称为第i+1层。
反之,退出第i+1层调用应该返回第i层。
采用图示方法描述递归函数的运行轨迹,从中可较直观地了解到各调用层次及其执行情况。
2-1应用案例
例用递归法计算n!
计算整数n的阶乘n!
是一个典型的递归问题。
使用递归方法来描述程序,十分简单且易于理解。
(1)描述递归关系
注意到,当n>
1时,n!
=n*(n−1)!
,这就是一种递归关系。
对于特定的k!
,它只与k和(k−1)!
有关。
递归边界为:
n=1时,n!
=1。
对于任意给定的n,程序将最终求解到1!
递归调用的实现
主函数调用f(n)后即进入函数f(n)执行。
设执行本程序时输入为n=5,即求5!
在主函数中的调用语句即为y=f(5),执行f函数,由于n=5,不等于1,故应执行g=n*f(n−1),即g=5*f(4)。
该语句调用f(4),…
进行4次递归调用后,f函数参数值变为1,故不再继续递归调用而开始逐层返回主调函数。
f
(1)的函数返回值为1,f
(2)的返回值为2*1=2,f(3)的返回值为3*2=6,f(4)的返回值为4*6=24,最后返回值f(5)为5*24=120。
例排队购票
一场球赛开始前,售票工作正在紧张进行中。
每张球票为50元,有m+n个人排队等待购票,其中有m个人手持50元的钞票,另外n个人手持100元的钞票。
求出这m+n个人排队购票,使售票处不至出现找不开钱的局面的不同排队种数。
(约定:
开始售票时售票处没有零钱,拿同样面值钞票的人对换位置为同一种排队。
递归设计要点
令f(m,n)表示有m个人手持50元的钞票,n个人手持100元的钞票时共有的排除总数。
分以下3种情况来讨论。
(1)n=0
n=0意味着排队购票的所有人手中拿的都是50元的钱币,注意到拿同样面值钞票的人对换位置为同一种排队,那么这m个人的排队总数为1,即f(m,0)=1。
(2)m<
n
当m<
n时,即购票的人中持50元的人数小于持100元的钞票,即使把m张50元的钞票都找出去,仍会出现找不开钱的局面,这时排队总数为0,即f(m,n)=0。
(3)其它情况
1)第m+n个人手持100元的钞票,则在他之前的m+n-1个人中有m个人手持50元的钞票,有n-1个人手持100元的钞票,此种情况共有f(m,n-1)。
2)第m+n个人手持50元的钞票,则在他之前的m+n-1个人中有m-1个人手持50元的钞票,有n个人手持100元的钞票,此种情况共有f(m-1,n)。
由加法原理得到f(m,n)的递归关系:
f(m,n)=f(m,n-1)+f(m-1,n)
初始条件:
n时,f(m,n)=0
当n=0时,f(m,n)=1
回顾递推算法的实现,提出思考斐波那契额数列实现的另一种方式问题,从而引出本课程内容。
借助多媒体课件,讲解递归概念,主要包括递归方式。
让学生动手实践汉诺塔递归实现过程。
1.应用递归设计输出杨辉三角。
搞清递推和递归的区别,设计递归算法的具体应用,需要加强实践。
5
掌握设计有效算法的分治策略,并掌握范例的设计技巧,
掌握计算算法复杂性方法。
分治法的基本思想及分治法的一般设计模式
分治算法的思想
1-1分治算法概述
1.分治法的设计思想
将一个难以直接解决的大问题,划分成一些规模较小的子问题,以便各个击破,分而治之。
更一般地说,将要求解的原问题划分成k个较小规模的子问题,对这k个子问题分别求解。
如果子问题的规模仍然不够小,则再将每个子问题划分为k个规模更小的子问题,如此分解下去,直到问题规模足够小,很容易求出其解为止,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解。
启发式规则:
1.平衡子问题:
最好使子问题的规模大致相同。
也就是将一个问题划分成大小相等的k个子问题(通常k=2),这种使子问题规模大致相等的做法是出自一种平衡(Balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。
2.独立子问题:
各子问题之间相互独立,这涉及到分治法的效率,如果各子问题不是独立的,则分治法需要重复地解公共的子问题。
分治法的典型情况
2分治法的求解过程
分治法的求解过程由以下三个阶段组成:
(1)划分:
既然是分治,当然需要把规模为n的原问题划分为k个规模较小的子问题,并尽量使这k个子问题的规模大致相同。
(2)求解子问题:
各子问题的解法与原问题的解法通常是相同的,可以用递归的方法求解各个子问题,有时递归处理也可以用循环来实现。
(3)合并:
把各个子问题的解合并起来,合并的代价因情况不同有很大差异,分治算法的有效性很大程度上依赖于合并的实现。
分治法的一般过程
DivideConquer(P)
{
if(P的规模足够小)直接求解P;
分解为k个子问题P1,P2,…Pk;
for(i=1;
i<
=k;
i++)
yi=DivideConquer(Pi);
returnMerge(y1,…,yk);
}
例二分检索
n个按非降次序排列的元素a[n],查找元素x是否在表中出现,若找到,返回其下标值,否则,返回一负数。
原问题可表示为:
I=(n,a[0],…,a[n-1],x)
分治的基本思路
数据分组:
a[0]~a[k-2];
a[k-1];
a[k]~a[n-1].
对应于三个子问题:
I1=(k-1,a[0],…,a[k-2],x);
I2=(1,a[k-1],x);
I3=(n-k,a[k],…,a[n-1],x).
例归并排序
二路归并排序的分治策略是:
将待排序序列r1,r2,…,rn划分为两个长度相等的子序列r1,…,rn/2和rn/2+1,…,rn;
分别对这两个子序列进行排序,得到两个有序子序列;
将这两个有序子序列合并成一个有序序列。
例快速排序
快速排序的分治策略是:
选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列r1…ri-1和ri+1…rn,前一个子序列中记录的值均小于或等于轴值,后一个子序列中记录的值均大于或等于轴值;
分别对划分后的每一个子序列递归处理;
由于对子序列r1…ri-1和ri+1…rn的排序是就地进行的,所以合并不需要执行任何操作。
回顾递归算法的实现,通过生活中解决复杂问题的分解方法,引出分治方法。
讲解分治法的基本思想及其一般算法的设计模式,介绍分治法的计算效率。
借助多媒体课件,通过具体例子采用分治思想来设计有效算法。
主要包括二分搜索技术、归并排序、快速排序。
让学生动手实践快速排序算法。
1.已知一个数组的大小,并且其中存在一个数,出现的频率大于50%,则称其为该数组的主元素。
6
第四章贪心算法
理解贪心算法的概念,
掌握贪心算法的基本要素。
多媒体讲授,讨论及PP