29
第第第 第第第第第第第

第四章 基本的算法策略

Embed Size (px)

DESCRIPTION

第四章 基本的算法策略. 4.1 迭代算法. 概念 用变量的旧值递推出新值的解决问题的方法 适合的范围 数值计算 类型 ( 1 )递推法 s n =s n-1 +A n ( 2 )倒推法. 4 . 1 . 1 递推 法. 【 例 1】 兔子繁殖问题 问题描述: 一对兔子从出生后第三个月开始,每月生一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死,一月份抱来一对刚出生的小兔子,问一年中每个月各有多少只兔子。 问题分析: 则繁殖过程如下: 一月 二月 三月 四月 五月 六月 …… - PowerPoint PPT Presentation

Citation preview

Page 1: 第四章 基本的算法策略

第四章 基本的算法策略

Page 2: 第四章 基本的算法策略

4.1 迭代算法• 概念 用变量的旧值递推出新值的解决问题的方法• 适合的范围 数值计算• 类型( 1 )递推法 sn=sn-1+An

( 2 )倒推法

Page 3: 第四章 基本的算法策略

4. 1. 1 递推法 【例 1 】兔子繁殖问题问题描述:一对兔子从出生后第三个月开始,每月生

一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死,一月份抱来一对刚出生的小兔子,问一年中每个月各有多少只兔子。

问题分析:则繁殖过程如下: 一月 二月 三月 四月 五月 六月 …… 1 1 1+1=2 2+1=3 3+2=5 5+3=8 ……数学建模: y1=y2=1 , yn=yn-1+yn-2 , n=3 , 4 ,

5 ,……。

Page 4: 第四章 基本的算法策略

算法 1 : main( ){ int i,a=1,b=1; print(a,b); for(i=1;i < =10;i++) { c=a+b; print (c); a=b; b=c ; } }

Page 5: 第四章 基本的算法策略

4.1.2 倒推法 所谓倒推法:是对某些特殊问题所采用的违反通常习惯的,从 后向前推解问题的方法。

Page 6: 第四章 基本的算法策略

【例】猴子吃桃问题一只小猴子摘了若干桃子,每天吃现有桃的一半多一个,到第 10 天时就只有一个桃子了,求原有多少个桃?数学模型:每天的桃子数为: a10=1, a9= ( 1+a10 ) *2, a8= ( 1+a9 ) *2,……a10=1 , 递推公式为: ai= ( 1+ai+1 ) *2 I = 9,8,7,6……1算法如下 : main( ) { int i,s; s=1; for (i=9 ;i>=1;i=i-1) s=(s+1 ) *2 print (s) ; }

Page 7: 第四章 基本的算法策略

4.2 蛮力法• 蛮力法是基于计算机运算速度快这一特性,在解决问题时采取的一种“懒惰”的策略。这种策略不经过(或者说是经过很少的)思考,把问题的所有情况或所有过程交给计算机去一一尝试,从中找出问题的解。

• 应用

蛮力策略的应用很广,具体表现形式各异,数据结构课程中学习的:选择排序、冒泡排序、插入排序、顺序查找、朴素的字符串匹配等,都是蛮力策略具体应用。

Page 8: 第四章 基本的算法策略

4 . 2 . 1 枚举法 枚举( enumerate )法(穷举法)是蛮力策略的一种表现形式,也是一种使用非常普遍的思维方法。它是根据问题中的条件将可能的情况一一列举出来,逐一尝试从中找出满足问题条件的解。但有时一一列举出的情况数目很大,如果超过了我们所能忍受的范围,则需要进一步考虑,排除一些明显不合理的情况,尽可能减少问题可能解的列举数目。

用枚举法解决问题,通常可以从两个方面进行算法设计:

1)找出枚举范围:分析问题所涉及的各种情况。

2 )找出约束条件:分析问题的解需要满足的条件,并用逻辑表达式表示。

Page 9: 第四章 基本的算法策略

【例】解数字迷: A B C A B × A D D D D D D算法设计 1 :按乘法枚举1) 枚举范围为: A : 3——9 ( A=1 , 2 时积不会得到六位数) ,B: 0——9, C: 0——9 六位数表示为 A*10000+B*1000+C*100+A*10

+B, 共尝试 800次。2)约束条件为: 每次尝试,先求 5 位数与 A 的积,再测试积的各位是否相 同,若相同则找到了问题的解。 测试积的各位是否相同比较简单的方法是,从低位开始, 每次都取数据的个位,然后整除 10 ,使高位的数字不断变 成个位,并逐一比较。

Page 10: 第四章 基本的算法策略

算法 1 如下:main ( ){ int A,B,C,D,E,E1,F,G1,G2,i; for(A=3; A<=9; A++) for(B=0; B<=9; B++) for(C=0; C<=9; C++) { F=A*10000+B*1000+C*100+A*10+B; E=F*A ; E1=E; G1=E1 mod 10; for(i=1; i<=5; i++) { G2=G1; E1=E1/10; G1= E1 mod 10; if(G1<>G2 ) break; } if(i=6) print( F ,” *” , A ,” =” , E); } }

Page 11: 第四章 基本的算法策略

4.3 分而治之算法

Page 12: 第四章 基本的算法策略

4 . 3 . 1 分治算法框架 1.算法设计思想

分治法求解问题的过程是,将整个问题分解成若干个小问题后分而治之。如果分解得到的子问题相对来说还太大,则可反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生出方便求解的子问题,必要时逐步合并这些子问题的解,从而得到问题的解。

分治法的基本步骤在每一层递归上都有三个步骤:

1 )分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题; 2 )解决:若子问题规模较小而容易被解决则直接解,否则再继续分解为更小的子问题,直到容易解决; 3 )合并:将已求解的各个子问题的解,逐步合并为原问题的解。

Page 13: 第四章 基本的算法策略

说明:

有时问题分解后,不必求解所有的子问题,也就不必作第三步的操作。比如折半查找,在判别出问题的解在某一个子问题中后,其它的子问题就不必求解了,问题的解就是最后(最小)

“ ”的子问题的解。分治法的这类应用,又称为 减治法 。

多数问题需要所有子问题的解,并由子问题的解,使用恰当的方法合并成为整个问题的解,比如合并排序,就是不断将子问题中已排好序的解合并成较大规模的有序子集。

Page 14: 第四章 基本的算法策略

2 .适合用分治法策略的问题当求解一个输入规模为 n且取值又相当大的问题时,用蛮力策略效率一般得不到保证。若问题能满足以下几个条件,就能用分治法来提高解决问题的效率。1)   能将这 n 个数据分解成 k 个不同子集合,且得到 k 个子集

合是可以独立求解的子问题,其中 1 < k≤n ;2)   分解所得到的子问题与原问题具有相似的结构,便于利用

递归或循环机制;在求出这些子问题的解之后,就可以推解出原问题的解;

Page 15: 第四章 基本的算法策略

4 . 3 . 2 二分法

不同于现实中对问题(或工作)的分解,可能会考虑问题(或工作)的重点、难点、承担人员的能力等来进行问题的分解和分配。在算法设计中每次一个问题分解成的子问题个数一般是固定的,每个子问题的规模也是平均分配的。当每次都将问题分解为原问题规模的一半时,称为二分法。二分法是分治法较常用的分解策略,数据结构课程中的折半查找、归并排序等算法都是采用此策略实现的。

Page 16: 第四章 基本的算法策略

分治法的一般的算法设计模式如下:Divide-and-Conquer(int n) /n为问题规模 /{ if ( n≤n0 ) /n0 为可解子问题的规模 / { 解子问题; return(子问题的解 ); }for ( i=1 ;i<=k;i++ ) /分解为较小子问题 p1,p2,……pk/ yi=Divide-and-Conquer(|Pi|); /递归解决 Pi/ T =MERGE(y1,y2,...,yk); /合并子问题 / return(T); }

Page 17: 第四章 基本的算法策略

【例 1 】金块问题: 老板有一袋金块 (共 n块 ) ,最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,我们希望用最少的比较次数找出最重的金块。

Page 18: 第四章 基本的算法策略

• 算法设计 1 : 比较简单的方法是逐个的进行比较查找。先拿两块比较重量,留下重的一个与下一块比较,直到全部比较完毕,就找到了最重的金子。算法类似于一趟选择排序,

算法如下: maxmin( float a[],int n)  { max==min=a[1];

for(i=2; i<=n ;i++ ) if(max < a[i]) max=a[i];   else if(min > a[i]) min=a[i];

}

Page 19: 第四章 基本的算法策略

算法分析算法分析 11 ::  算法中需要算法中需要 n-1n-1次比较得到次比较得到 maxmax 。最好的情况是金块是由小到。最好的情况是金块是由小到大取出的,不需要进行与大取出的,不需要进行与 minmin 的比较,共进行的比较,共进行 n-1n-1次比较。最坏次比较。最坏的情况是金块是由大到小取出的,需要再经过的情况是金块是由大到小取出的,需要再经过 n-1n-1次比较得到次比较得到 miminn

Page 20: 第四章 基本的算法策略

算法设计算法设计 2:2:

  在含  在含 nn (( nn 是是 22 的幂(的幂( n>=2n>=2 ))个元素的集合))个元素的集合中寻找极大元和极小元。用分治法(二分法):中寻找极大元和极小元。用分治法(二分法):

11 ) 将数据等分为两组(两组数据可能差) 将数据等分为两组(两组数据可能差 11 ), ),   

22 ) 递归分解直到每组元素的个数≤) 递归分解直到每组元素的个数≤ 22 ,可简单地,可简单地找找  到最大(小)值。  到最大(小)值。33 ) 回溯时将分解的两组解大者取大,小者取小,) 回溯时将分解的两组解大者取大,小者取小,  合并为当前问题的解。  合并为当前问题的解。

Page 21: 第四章 基本的算法策略

算法算法 22 递归求取最大和最小元素 递归求取最大和最小元素 float a[n];maxmin ( int i, int j ,float &fmax, float &fmin ) {int mid; float lmax, lmin, rmax, rmin;if (i=j) {fmax= a[i]; fmin=a[i];}else if (i=j-1)   if(a[i]<a[j]) { fmax=a[j]; fmin=a[i];}   else {fmax=a[i]; fmin=a[j];}   else {mid=(i+j)/2; maxmin ( i , mid, lmax, lmin ) ; maxmin ( mid+1 , j, rmax, rmin ) ;if(lmax>rmax) fmax=lmax;else fmax=rmax;if(lmin>rmin) fmin=rmin;else fmin=lmin;}

Page 22: 第四章 基本的算法策略

【例】大整数乘法在某些情况下,我们需要处理很大的整数,它无法在计算机硬件能直接允许的范围内进行表示和处理。若用浮点数来存储它,只能近似地参与计算,计算结果的有效数字会受到限制。若要精确地表示大整数,并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。请设计一个有效的算法,可以进行两个 n位大整数的乘法运算。

Page 23: 第四章 基本的算法策略

算法设计:设 X和 Y 都是 n位的二进制整数,现在要计算它们的乘积 X*Y 。

图 4-10 大整数 X和 Y的分段

Page 24: 第四章 基本的算法策略

按照乘法分配律,分解后的计算过程如下:记: X=A*2n/2+B , Y=C*2n/2+D。这样, X和 Y的乘积为:X*Y=(A*2n/2+B)(C*2n/2+D)=A*C*2n+(AD+CB)*2n/2+B*D    (1)

Page 25: 第四章 基本的算法策略

T( 1 ) =1 T( n ) =4T(n/2) ( 2 )

由此递归式迭代过程如下:T(n)=4T(n/2)  =4(4T(n/4) )=4*4T(n/4) =16*4T(n/8) =…… =O( 4k) = O(nlog4) =O( n2 )所以可得算法的时间复杂度为 T(n)=O(n2) 。

Page 26: 第四章 基本的算法策略

模型改进:可以把 X*Y 写成另一种形式:X*Y=A*C*2n+[(A-B)(D-C)+AC+BD]*2n/2+B*D (3)

Page 27: 第四章 基本的算法策略

式 (3)看起来比式 (1)复杂,但它仅需做 3次 n/2位整数的乘法:AC, BD和 (A-B)(D-C) , 6次加、减法和 2次移位。由此可得 :

(4)

用解递归方程的迭代公式法,不妨设 n=2k: T(n)=3T(n/2) =3(3T(n/4)) =9(T(n/8) =…… =3k +3k-1 *2c+3k-2 *4c+……+3c2k-1+c2k = O(nlog3)则得到 T(n)=O(nlog3)=O(n1.59) 。

Page 28: 第四章 基本的算法策略

4 . 3 . 4 其它分治方法

Page 29: 第四章 基本的算法策略

【例】选择问题: 对于给定的 n 个元素的数组 a[0:n-1],要求从中找出第 k小的元素。

问题分析:选择问题的一个应用就是寻找中值元素,此时 k=[n/2]。

快速排序算法来解决选择问题,一趟排序分解出的左子集中元素个数 nleft, 可能是以下几种情况:

1)  nleft=k-1 ,则分界数据就是选择问题的答案。 2)  nleft>k-1 ,则选择问题的答案继续在左子集中找,问 题规模变小了。 3)  nleft<k-1 ,则选择问题的答案继续在右子集中找,问 题变为选择第 k-nleft-1 小的数,问题的规模也变小了。