算法分析总结课件.docx
- 文档编号:26884262
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:22
- 大小:810.19KB
算法分析总结课件.docx
《算法分析总结课件.docx》由会员分享,可在线阅读,更多相关《算法分析总结课件.docx(22页珍藏版)》请在冰豆网上搜索。
算法分析总结课件
递归与分治策略2
1.递归2
2.递归函数2
3.阶乘函数3
4.斐波那契数列3
5.整数划分3
6.分治法4
7.大整数的乘法5
8.矩阵乘6
9.合并排序7
10.棋盘覆盖8
11.循环赛日程表8
12.快速排序9
13.贪心算法9
14.贪心算法基本要素9
15.活动安排问题10
16.0-1背包问题与背包问题11
0-1背包问题11
0-1背包问题改进算法11
17.最优装载11
18.单源最短路径12
19.Dijkstra算法13
20.最小生成树13
21.多机调度算法17
22.备忘录方法17
24.凸多边形最优三角剖分18
25.长公共子序列19
26.多边性游戏20
27.二分搜索技术21
递归与分治策略
1.递归
递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
函数嵌套调用过程示例
1.子问题须与原始问题为同样的事,且更为简单;
2.不能无限制地调用本身,须有个出口,化简为非递归状况处理。
在数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,并规定其他所有情况都能被还原为其基本情况。
例如,下列为某人祖先的递归定义:
某人的双亲是他的祖先(基本情况)。
某人祖先的双亲同样是某人的祖先(递归步骤)。
斐波纳契数列(FibonacciSequence),又称黄金分割数列,指的是这样一个数列:
1、1、2、3、5、8、13、21.....I[1]
斐波纳契数列是典型的递归案例:
2.递归函数
递归方法——汉诺塔
3.阶乘函数
下面是求10的阶乘,你参考下:
voidmain
{
intfn=1,i=1;
intn=10;
//下面就是求10的阶乘
for(i=1;i<=n;i++)
{
fn=fn*i;
}
printf("10的阶乘是%d",fn);
}
4.斐波那契数列
即定义两个数字,后面的数字是前两个数字之和a1=1,a2=1,a3=2,......an=an-1+an-2(n>=3)
斐波那契数列很有趣,每一个数都是整型数,可是它的通项公式却由无理数进行表达。
斐波那契数列的通用表达是:
第一个数和第二个数是1,从第三个数开始,每一个数都是它的前两个数的和。
a1=1,a2=1,a3=2,......an=an-1+an-2(n>=3),用C言代码可以实现第几个斐波那契数。
5.整数划分
◎根据n和m的关系,考虑以下几种情况:
其中n为要划分的正整数,m是划分中的最大加数
1.当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
2.当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
3.当n=m时,根据划分中是否包含n,可以分为两种情况:
(1)划分中包含n的情况,只有一个即{n};
(2)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此f(n,n)=1+f(n,n-1);
4.当n 5.但n>m时,根据划分中是否包含最大值m,可以分为两种情况: (1)划分中包含m的情况,即{m,{x1,x2,...xi}},其中{x1,x2,...xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分个数为f(n-m,m); (2)划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);因此f(n,m)=f(n-m,m)+f(n,m-1); 综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中 (1)和 (2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。 而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。 其递推表达式如下: ∙f(n,m)=1;(n=1orm=1) ∙f(n,m)=f(n,n);(n ∙1+f(n,m-1);(n=m) ∙f(n-m,m)+f(n,m-1);(n>m) 6.分治法 分治法在每一层递归上都有三个步骤: 分解: 将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题; 解决: 若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题; 合并: 将各个子问题的解合并为原问题的解。 分治策略的例子: 合并排序,快速排序,折半查找,二叉遍历树及其相关特性。 7.大整数的乘法 设X和Y都是n位的二进制整数,现在要计算它们的乘积XY。 我们可以用小学所学的方法来设计一个计算乘积XY的算法,但是这样做计算步骤太多,显得效率较低。 如果将每2个1位数的乘法或加法看作一步运算,那么这种方法要作O(n2)步运算才能求出乘积XY。 下面我们用分治法来设计一个更有效的大整数乘积算法。 x=|A|B| y=|C|D| 图6-3大整数X和Y的分段 我们将n位的二进制整数X和Y各分为2段,每段的长为n/2位(为简单起见,假设n是2的幂),如图6-3所示。 由此,X=A2n/2+B,Y=C2n/2+D。 这样,X和Y的乘积为: XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD (1) 如果按式 (1)计算XY,则我们必须进行4次n/2位整数的乘法(AC,AD,BC和BD), 以及3次不超过n位的整数加法(分别对应于式 (1)中的加号),此外还要做2次移位(分别对应于式 (1)中乘2n和乘2n/2)。 所有这些加法和移位共用O(n)步运算。 设T(n)是2个n位整数相乘所需的运算总数,则由式 (1),我们有: T (1)=1 T(n)=4T(n/2)+O(n) (2) 由此可得T(n)=O(n2)。 因此,用 (1)式来计算X和Y的乘积并不比小学生的方法更有效。 要想改进算法的计算复杂性,必须减少乘法次数。 为此我们把XY写成另一种形式: XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD (3) 虽然,式(3)看起来比式 (1)复杂些,但它仅需做3次n/2位整数的乘法(AC,BD和(A-B)(D-C)),6次加、减法和2次移位。 由此可得: T (1)=1 T(n)=3T(n/2)+cn (4) 用解递归方程的套用公式法马上可得其解为T(n)=O(nlog3)=O(n1.59)。 利用式(3),并考虑到X和Y的符号对结果的影响,我们给出大整数相乘的完整算法MULT如下: functionMULT(X,Y,n);{X和Y为2个小于2n的整数,返回结果为X和Y的乘积XY} 8.矩阵乘 分治策略将2个二阶矩阵采用下列方式来计算: 其中: 数一下,这样来计算2个二阶矩阵的乘法用了7次乘法,18次加法。 而蛮力法用了8次乘法和4次加法。 当然,这还不能体现出它的优越性,它的优越性表现在当矩阵的阶趋于无穷大时的渐进效率。 由上面的式子,根据矩阵的相关知识,对于分块矩阵,也可以写成上述形式: 9.合并排序 10.棋盘覆盖 11.循环赛日程表 算法思路: 按分治策略,我们可以将所有的选手分为两半,则n个选手的比赛日程表可以通过n/2个选手的比赛日程表来决定。 递归地用这种一分为二的策略对选手进行划分,直到只剩下两个选手时,比赛日程表的制定就变得很简单。 这时只要让这两个选手进行比赛就可以了。 如上图,所列出的正方形表是8个选手的比赛日程表。 其中左上角与左下角的两小块分别为选手1至选手4和选手5至选手8前3天的比赛日程。 据此,将左上角小块中的所有数字按其相对位置抄到右下角,又将左下角小块中的所有数字按其相对位置抄到右上角,这样我们就分别安排好了选手1至选手4和选手5至选手8在后4天的比赛日程。 依此思想容易将这个比赛日程表推广到具有任意多个选手的情形。 12.快速排序 13.贪心算法 贪婪算法可解决的问题通常大部分都有如下的特性: ⑴随着算法的进行,将积累起其它两个集合: 一个包含已经被考虑过并被选出的候选对象,另一个包含已经被考虑过但被丢弃的候选对象。 ⑵有一个函数来检查一个候选对象的集合是否提供了问题的解答。 该函数不考虑此时的解决方法是否最优。 ⑶还有一个函数检查是否一个候选对象的集合是可行的,也即是否可能往该集合上添加更多的候选对象以获得一个解。 和上一个函数一样,此时不考虑解决方法的最优性。 ⑷选择函数可以指出哪一个剩余的候选对象最有希望构成问题的解。 ⑸最后,目标函数给出解的值。 ⑹为了解决问题,需要寻找一个构成解的候选对象集合,它可以优化目标函数,贪婪算法一步一步的进行。 起初,算法选出的候选对象的集合为空。 接下来的每一步中,根据选择函数,算法从剩余候选对象中选出最有希望构成解的对象。 如果集合中加上该对象后不可行,那么该对象就被丢弃并不再考虑;否则就加到集合里。 每一次都扩充集合,并检查该集合是否构成解。 如果贪婪算法正确工作,那么找到的第一个解通常是最优的。 14.贪心算法基本要素 贪心算法的基本要素: 1.贪心选择性质。 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。 这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。 动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。 对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。 2.当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。 问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 贪心算法的基本思路: 从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。 当达到算法中的某一步不能再继续前进时,算法停止。 该算法存在问题: 1.不能保证求得的最后解是最佳的; 2.不能用来求最大或最小解问题; 3.只能求满足某些约束条件的可行解的范围。 实现该算法的过程: 从问题的某一初始解出发; while能朝给定总目标前进一步do 求出可行解的一个解元素; 由所有解元素组合成问题的一个可行解; 贪心算法思想: 顾名思义,贪心算法总是作出在当前看来最好的选择。 也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。 当然,希望贪心算法得到的最终结果也是整体最优的。 虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。 如单源最短路经问题,最小生成树问题等。 在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。 15.活动安排问题 问题描述: 设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。 每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si 如果选择了活动i,则它在半开时间区间[si,fi)内占用资源。 若区间[si,fi)与区间[sj,fj)不相交,则称活动i与活动j是相容的。 也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。 16.0-1背包问题与背包问题 0-1背包问题 0-1背包问题改进算法 17.最优装载 问题描述: 有一批集装箱要装上一艘载重量为c的轮船。 其中集装箱i的重量为Wi。 最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。 编程任务: 对于给定的n个集装箱和轮船的载重量C,编程计算装入最多时的集装箱个数。 输入: 输入由多组测试数据组成。 每组测试数据输入的第1行中有2个正整数n和C。 正整数n是集装箱个数;正整数C是轮船的载重量。 接下来的一行中有n个整数,分别表示n个集装箱的重量,它们之间用空格分隔。 其中1<=n<=2000,所有正整数不超过231-1 输出: 对应每组输入,输出的每行是计算出的装入最多时的集装箱个数。 样例输入: 45 3521 样例输出: 2 解决: 贪心算法入门题,其实代码可以很短的,就是选择最小的装在里边就行了,但是还是练习下记录哪个装入为好 18.单源最短路径 19.Dijkstra算法 1.dijkstra算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法。 算法解决的是有向图中单个源点到其他顶点的最短路径问题,其主要特点是每次迭代时选择的下一个顶点是标记点之外距离源点最近的顶点。 但由于dijkstra算法主要计算从源点到其他所有点的最短路径,所以算法的效率较低。 2.dijkstra算法基本过程 假设路网中每一个节点都有标号 是从出发点s到点t的最短路径长度;表示从s到t的最短路径中t点的前一个点。 求解从出发点s到点t的最短路径算法的基本过程为: 1. 初始化。 出发点设置为: 标记起源点s,记k=s,其他所有点设为未标记。 2. 检验从所有已标记的点k到其他直接连接的未标记的点j的距离,并设置: 3. 选取下一个点。 从所有未标记的点中选取最小的点i,点i被选为最短路径中的一点,并设为已标记的。 4. 找到点i的前一点。 从已经标记的点集合中找到直接连接到点i的点,并标记为。 5. 标记点i。 如果所有的点已标记,则算法结束。 否则,记k=i,转到2继续。 从以上算法的步骤中可以看出: dijkstra算法的关键部分是从未标记的点中不断地找出距离源点距离最近的点,并把改点加入到标记的点集合中,同时更新未标记的点集合中其余点到起始点的最短估计距离[z1] 。 20.最小生成树 Prim 任选一个定点,以该顶点为基础,选出离他最近的一个点,然后就是距这两个定点最近的一个点。 以此类推,直到所有点都遍历一次。 此为原始的加权连通图。 每条边一侧的数字代表其权值。 - - - 顶点D被任意选为起始点。 顶点A、B、E和F通过单条边与D相连。 A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C,G A,B,E,F D 下一个顶点为距离D或A最近的顶点。 B距D为9,距A为7,E为15,F为6。 因此,F距D或A最近,因此将顶点F与相应边DF以高亮表示。 C,G B,E,F A,D 算法继续重复上面的步骤。 距离A为7的顶点B被高亮表示。 C B,E,G A,D,F 在当前情况下,可以在C、E与G间进行选择。 C距B为8,E距B为7,G距F为11。 E最近,因此将顶点E与相应边BE高亮表示。 无 C,E,G A,D,F,B 这里,可供选择的顶点只有C和G。 C距E为5,G距E为9,故选取C,并与边EC一同高亮表示。 无 C,G A,D,F,B,E 顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG。 无 G A,D,F,B,E,C 现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。 在此例中,最小生成树的权值之和为39。 无 无 A,D,F,B,E,C,G Kruskal 图例描述: 首先第一步,我们有一张图Graph,有若干点和边 将所有的边的长度排序,用排序的结果作为我们选择边的依据。 这里再次体现了贪心算法的思想。 资源排序,对局部最优的资源进行选择,排序完成后,我们率先选择了边AD。 这样我们的图就变成了右图 在剩下的变中寻找。 我们找到了CE。 这里边的权重也是5 依次类推我们找到了6,7,7,即DF,AB,BE。 下面继续选择,BC或者EF尽管现在长度为8的边是最小的未选择的边。 但是现在他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连)。 所以不需要选择他们。 类似的BD也已经连通了(这里上图的连通线用红色表示了)。 最后就剩下EG和FG了。 当然我们选择了EG。 最后成功的图就是右: 21.多机调度算法 ◎处理时间最长的作业分配给最先空闲的机器 采用最长处理时间作业优先的贪心算则策略设计出解多机调度问题的较好的近似算法。 1.当n<=m时,只要将作业时间区间分配给作业即可。 时间为最长时间的作业。 2.当n>m时,首先将n个作业从大到小排序。 然后依此顺序分步将作业分配给空闲的处理机,每步分配给一个机器,而且需要考虑分配哪一个作业。 根据这种思想可利用如下贪心原则: 从剩下的作业中,选择需要处理时间最长。 然后依次选择处理时间次长的作业,直到所有的作业全部处理完毕,或者机器不能再处理其他作业。 22.备忘录方法 动态规划算法的一个变形是备忘录方法。 备忘录方法也用一个表格来保存已解决的子问题的答案,在下次需要解决此问题时,只要简单地查看该子问题的解答,而不必重新计算。 与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。 因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。 备忘录方法为每个子问题建立了一个记录项,初始化时,该记录项存入一个特殊的值,表示该子问题尚未求解。 在求解过程中,对每个待求的子问题,首先查看相应的记录项。 若记录项中存储的是初始化时存入的特殊值,则表示该子问题是第一次遇到,则此时计算出该子问题的解,并保存在相应的记录项中。 若记录项中存储的已不是初始化时存入的特殊值,则表示该问题已被计算过,其相应的记录项中存储的是该子问题的解答。 此时,只要从记录项中取出该子问题的解答即可。 一般来讲,当一个问题的所有子问题至少要解一次时,则用动态规划算法比用备忘录算法好。 此时,动态规划算法没有任何多余的计算,还可利用其规则的表格存取方式,来减少在动态规划算法中的计算时间和空间需求。 当子问题空间中部分子问题可不必求解时,用备忘录方法则较有利,因为从其控制结构可以看出,该方法只解那些确实需要求解的子问题。 24.凸多边形最优三角剖分 题目描述: 用多边形顶点的逆时针序列表示凸多边形,即P={v0,v1,…,vn-1}表示具有n条边的凸多边形。 给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。 要求确定该凸多边形的三角剖分,使得即该三角剖分中诸三角形上权之和为最小。 解题思路: 若凸(n+1)边形P={v0,v1,…,vn-1}的最优三角剖分T包含三角形v0vkvn,1≤k≤n-1,则T的权为3个部分权的和: 三角形v0vkvn的权,子多边形{v0,v1,…,vk}和{vk,vk+1,…,vn}的权之和。 可以断言,由T所确定的这2个子多边形的三角剖分也是最优的。 因为若有{v0,v1,…,vk}或{vk,vk+1,…,vn}的更小权的三角剖分将导致T不是最优三角剖分的矛盾。 那么我们定义一个t[i][j],1<=i<=j<=N,为凸子多边形{vi-1,vi,…,vj}的最优三角剖分所对应的权函数值,即其最优值。 据此定义,要计算的凸(n+1)边形P的最优权值为t[1][n]。 t[i][j]的值可以利用最优子结构性质递归地计算。 当j-i≥1时,凸子多边形至少有3个顶点。 由最优子结构性质,t[i][j]的值应为t[i][k]的值加上t[k+1][j]的值,再加上三角形vi-1vkvj的权值,其中i≤k≤j-1。 由于在计算时还不知道k的确切位置,而k的所有可能位置只有j-i个,因此可以在这j-i个位置中选出使t[i][j]值达到最小的位置。 由此,t[i][j]可递归地定义为: 对于要求的t[1][n],可以用通过由下至上的,从链长(多边形的边)为2开始计算,每次求t[i][j]的最小值,并且记录最小值所对应的K值,根据最优子结构的性质,逐步向上就可以求出t[1][n]的最小值。 类似的,求三角划分顶点的乘积的最小值问题,也是一样的。 25.长公共子序列 问题描述: 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。 令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列 例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。 考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。 不难证明有以下性质: (1)如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列; (2)如果am-1! =bn-1,则若zk-1! =am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列; (3)如果am-1! =bn-1,则若zk-1! =bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。 这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1! =bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。 凸多边形最优三角剖分 也就是凸多边形内部弦的最短长度 26.多边性游戏 游戏规则: (1)首先,移走一条边。 (2)然后进行下面的操作: 选中一条边E,该边有两个相邻的顶点,不妨称为V1和V2。 对V1和V2顶点所标的整数按照E上所标运算符号(+或是×)进行运算,得到一个整数;用该整数标注一个新顶点,该顶点代替V1和V2。 持续进行此操作,直到最后没有边存在,即只剩下一个顶点。 该顶点的整数称为此次游戏的得分(Score)。 多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。 每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“*”。 所有边依次用整数从1到n编号。 游戏第1步,将一条边删除。 随后n-1步按以下方式操作: (1)选择一条边E以及由E连接着的2个顶点V1和V
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 分析 总结 课件