1、第7章:算法基础,算法是一个程序的灵魂,它是在有限步骤内求解某一问题所使用的一组定义明确的规则。具体衡量标准包括时间复杂度和空间复杂度。基本有数值和非数值两种分类。,目录,7.1算法 7.2算法评价 7.3常用算法 7.4具体算法实例,7.1 算法概述,例子: 从10个数中挑选出最大的数具体思路:可以用“打擂台”来比喻, 先有任意一个人在台上,然后第二个人与他比武, 胜者留在台上,如此继续,直到第十个人比较为止 (一共比9次)最后留在台上者为胜。,用计算机算法描述: (1)选数放在A中,设一记数器N,N=0。 (2)将下一个数与A中的数相比,大者放入A中。 (3)使N的值增加1(比较次数)。
2、(4)如果N的值小于9,则执行第(2)步, 如果的值大于或等于9,停止循环, 此时A中的数是最大的数。,算法是一个程序的灵魂,编程工具可以变,用户接口可以变, 但一个程序的核心永远是它的算法和数据结构。,算法是在有限步骤内求解某一问题所使用的一组定义明确的规则。 通俗点说,就是计算机解题的过程。在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法。前者是推理实现的算法后者是操作实现的算法。,算法特征 有穷性 确切性 输入 输出 可行性,常用的算法设计方法数值算法如迭代法、递归法等非数值算法如分治法、贪心法等,7.2 算法评价,算法评价标准 算法是正确的 执行算法所耗费的时间。 执行
3、算法所耗费的存储空间,其中主要考虑辅助存储空间。 算法应易于理解、易于编码、易于调试。,7.3 常用的算法,穷举法 迭代法 递归法 递推法 贪心法 分治法,7.3.1 穷举法,【例7-1】设有A、B、C、D四个数都在116范围内。 要求打印出4个数都不相同时,其和为34的所有值。,算法分析:最直接的想法是设置A、B、C、D四个变量, 都从116循环。但这需判断A、B、C、D四数有所重 复的情况。我们可以加上一定的限制条件,ABCD, 设ABCD,这样可以设A的初值为1,B的初值为A+1, C的初值为B+1,D的初值为C+1。每一个循环的终值 (可能的最大数)我们也可以计算出来。A+A+1+A+
4、2+A+3=34, 故A=7;1+B+B+1+B+2=34,故B=10;1+2+C+ C+1=34, 故C=15;D=C+1,故D=16。,7.3.2 迭代法,迭代法适用于方程(或方程组)求解,是使用间接方法求方程近似根的一种常用算法。,算法分析: 1首先选一个x的近似根x0,从x0出发,代入右面函数,求解方程f1(x)=f2(x0)得到下一个近似根x1。 2将上次近似根x1代入右面函数,求解方程f1(x)=f2(x1),得到另一个近似根x2。 3重复2的计算,得到一系列的近似根x0,x1,x2,xi, xi+1,xn,若方程有根。这数列收敛于方程的根。 如满足 xn-xn-1,则认为xn是方
5、程的近似根。,【例7-2】用迭代法求方程的根 f(x)=x+ex=0,7.3.3 递归法,程序调用自身的编程技巧称为递归(recursion)。一个比较经典的描述是老和尚讲故事,他说从前有座山, 山上有座庙,庙里有个老和尚在讲故事,他说从前有座山, 山上有座庙,庙里有个老和尚在讲故事,他说从前有座山, 。这样没完没了地反复讲故事,直到最后老和尚烦了 停下来为止。,递归的关键在于找出递归方程式和递归终止条件。 即老和尚反复讲故事这样的递归方程式要有, 最后老和尚烦了停下来这样的递归的终止条件也要有,【例7-3】裴波那契数列f(n)=f(n-1)+f(n-2);f(0)=1;f(1)=2 【例7-
6、4】梵塔问题:有n个半径各不相同的圆盘,按半径从大到小,自下而上依次套在A柱上,另外还有B、C两根空柱。要求将A柱上的n个圆盘全部搬到C柱上去,每次只能搬动一个盘子,且必须始终保持每根柱子上是小盘在上,大盘在下。,7.3.4 递推法,【例7-6】猴子吃桃小猴子第一天摘下若干个桃子,当即吃掉了一半, 还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半, 又多吃一个。以后每天早上都吃了前一天剩下的一半,又多吃一个。 到第10天早上猴子想再吃时,见到只剩下一个桃子了。问第一天 猴子共摘了多少个桃子。这是典型的倒推问题。从最后一天起逐天推算出前一天的桃子数 ,直到推出第1天为止。设第n天桃子数为
7、x0,已知它是前一天的 桃子数xn-1的一半再减去1, 即:x(n)=1/2*x(n-1)-1利用此公式可以从第n天的桃子数推出其前一天的桃子数。边界条件为:x(10)=1,7.3.5 贪心法,贪心法的基本思路:从问题的某一个初始解出发逐步逼近 给定的目标,以尽可能快的求得更好的解。当达到某算法 中的某一步不能再继续前进时,算法停止。该算法存在问题: 不能保证求得的最后解是最佳的,不能用来求最大或最小解 问题,只能求满足某些约束条件的可行解的范围。,实现该算法的过程: (1)从问题的某一初始解出发。 (2)while能朝给定总目标前进一步do。 (3)求出可行解的一个解元素。 (4)由所有解元
8、素组合成问题的一个可行解。,【例7-7】删数问题 键盘输入一个高精度的正整数N,去掉其中任意S个数字后使 剩下的数最小。例如:N=175438、S=4,可以删去7、5、4、8、得到13。分析:很容易想到用贪心法,但是贪心法标准是什么呢? 删S次,每次删的数要使剩下的数尽量小。例如上面的例子,第一次删7,至少比第一次删1、5、4、3、8好!这样,删数过程是:175438 15438 1438 138 13 实现很简单,就是从左向右找到第一个i,使nini+1,如果找到了,就删第i个,否则删最后一位。这里一次选择的i是2,2,2,3,因此解向量是:(2,2,2,3),7.3.6 贪心法,贪心法的基
9、本思路:从问题的某一个初始解出发逐步逼近 给定的目标,以尽可能快的求得更好的解。当达到某算法 中的某一步不能再继续前进时,算法停止。该算法存在问题: 不能保证求得的最后解是最佳的,不能用来求最大或最小解 问题,只能求满足某些约束条件的可行解的范围。,实现该算法的过程: (1)从问题的某一初始解出发。 (2)while能朝给定总目标前进一步do。 (3)求出可行解的一个解元素。 (4)由所有解元素组合成问题的一个可行解。,7.3.6 分治法,分治的基本思想是将一个规模为n的问题分解 为k个规模较小的子问题,这些子问题互相独立 且与原问题相同。找出各部分的解,然后把各部分 的解组合成整个问题的解。
10、解决算法实现的同时, 需要估算算法实现所需时间。分治算法时间是这样 确定的:解决子问题所需的工作总量(由子问题的 个数、解决每个子问题的工作量决定)合并所有子 问题所需的工作量。分治法是把任意大小问题尽可 能地等分成两个子问题的递归算法分治的具体过程:,begin 开始if 问题不可分 then 返回问题解else begin从原问题中划出含一半运算对象的子问题1;递归调用分治法过程,求出解1;从原问题中划出含另一半运算对象的子问题2;递归调用分治法过程,求出解2; 将解1、解2组合成整个问题的解; end;end; 结束,【例7-8】金块问题 老板有一袋金块(共n块,n是2的幂(n2),将有
11、两名最优秀的雇员每人得到其中的一块,排名第一的得到最重的那块,排名第二的雇员得到袋子中最轻的金块。假设有一台比较重量的仪器,我们希望用最少的比较次数找出最重的金块。 分析:问题可以简化为:在含n(n是2的幂(n2)个元素的集合中寻找极大元和极小元。明显的方法是逐个的进行比较查找。,7.4 应用实例,简易赛车游戏算法 五子棋算法 加密/解密算法,7-4-1 简易赛车游戏算法,简单的游戏往往更耐玩,所谓的赛车也只有4个方块。 第一步,绘制对象:用函数drawcar()画赛车,drawway(n)画跑道的第n层。 第二步,接受控制:Form的KeyPreview属性要设为true,在Form_Key
12、Press函数中通过改变全局变量cx来控制赛车的位置。 第三步,游戏循环:作为即时游戏,必须要有一个Timer,并在其事件Timer1_Timer()中绘制所有对象和进行碰撞检测。本例中,绘图部分写在了Timer1_Timer()中,碰撞测试放在了test()中。这也是所有即时游戏所共通的框架。当然,我们往往还是根据具体的设计作一些变通,发挥一些技巧,比如这里设计的跑道是随机产生的,这就要通过一点技巧以便既让玩家感到挑战,又不至于出现不可逾越的难关,7-4-2 五子棋算法,五子棋的核心算法,由6个基本功能模块构成,各模块详细分析如下: (1)初始化:在屏幕上画出棋盘。 (2)主循环控制模块:控
13、制下棋顺序,当轮到某方下子时,负责将程序转到相应的模块中去,主要担当一个调度者的角色。 (3)玩家下子:当轮到玩家下时,您通过键盘或鼠标在棋盘上落子,程序会根据该点的位置记录2,以表明该子是玩家下的。 (4)盘面分析填写棋型表:本程序核心模块之一,人工智能算法的根本依据!其具体实现方法如下:您在下五子棋时,一定会先根据棋盘上的情况,找出当前最重要的一些点位,如“活三”、“冲四”等;然后再在其中选择落子点。但是,电脑不会像人一样分析问题,要让它知道哪是“活三”、哪是“冲四”,就得在棋盘上逐点计算,一步一步的教它。 (5)电脑下子:有了上面填写的两张棋型表,现在要做的就是让电脑知道在哪一点下子了。其中最简单的计算方法,就是遍历棋型表找出其中数值最大的一点,在该点下子即可。但这种算法的弱点非常明显,只顾眼前利益,不能顾全大局,这就和许多五子棋初学者一样犯了“目光短浅”的毛病。 (6)胜负判断:某方形成五子连即获胜;若黑棋走出“双三”、“双四”或长连即以禁手判负。,7-4-3 加密/解密,本算法主要是进行目前流行的加解密的一道简单实用算法,本章结束,