ImageVerifierCode 换一换
格式:PPT , 页数:46 ,大小:839.50KB ,
文档编号:4908201      下载积分:25 文币
快捷下载
登录下载
邮箱/手机:
温馨提示:
系统将以此处填写的邮箱或者手机号生成账号和密码,方便再次下载。 如填写123,账号和密码都是123。
支付方式: 支付宝    微信支付   
验证码:   换一换

优惠套餐
 

温馨提示:若手机下载失败,请复制以下地址【https://www.163wenku.com/d-4908201.html】到电脑浏览器->登陆(账号密码均为手机号或邮箱;不要扫码登陆)->重新下载(不再收费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录  
下载须知

1: 试题类文档的标题没说有答案,则无答案;主观题也可能无答案。PPT的音视频可能无法播放。 请谨慎下单,一旦售出,概不退换。
2: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
3: 本文为用户(晟晟文业)主动上传,所有收益归该用户。163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

1,本文(算法设计与分析-第03周-分治策略2课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!

算法设计与分析-第03周-分治策略2课件.ppt

1、第2章 分治策略(2)教学目的与要求1.掌握设计有效算法的分治策略。2.要求通过范例的学习掌握分治策略的技巧。2.9 线性时间选择线性时间选择v给定线性序集中n个元素和一个整数k,1kn,要求找出这n个元素中第k小的元素。v采用分治策略,利用在快速排序中使用到的RandomizedPartition算法,将序列随机分成两部分api和ai+1r,使得api的每个元素都不大于ai+1r的每个元素,而此时ai恰好为第i小元素,接着计算子数组api的元素个数j,如果kj,则apr中第k小的数落在子数组api中,如果kj,则apr中第k小的数落在子数组ai+1r中,此时要找的apr中第k小的元素是ai+

2、1r中第k-j小的元素。vtemplatevint Partition(Type a,int p,int r)vv int i=p,j=r+1;v Type x=ap,t;v /将 x的元素交换到右边区域v while(true)v v while(a+i x);/从右到左找到第一个不大于ap的元素ajv if(i=j)break;v t=ai;ai=aj;aj=t;/交换ai和ajv v ap=aj;aj=x;/交换ap和ajv return j;vvtemplatevint RandomizedPartition(Type a,int p,int r)vv int i=Random(p,r

3、);v Type t;v t=ai;ai=ap;ap=t;v return Partition(a,p,r);vvtemplatevType RandomizedSelect(Type a,int p,int r,int k)vv int i,j;v if(p=r)return ap;v i=RandomizedPartition(a,p,r);v j=i-p+1;/计算子数组api的元素个数jv if(k=j)return RandomizedSelect(a,p,i,k);v else return RandomizedSelect(a,i+1,r,k-j);vv在最坏情况下(如在找最小元

4、素时,总在最大元素处划分),算法RandomizedSelect需要(n2)计算时间,但该算法的平均性能较好。v如果能在线性时间内找到一个划分基准,使得按这个基准所划分出的2个子数组的长度都至少为原数组长度的倍(01是某个正常数),那么就可以在最坏情况下在最坏情况下用O(n)时间完成选择任务。例如,若=9/10,算法递归调用所产生的子数组的长度至少缩短1/10。所以,在最坏情况下,算法所需的计算时间T(n)满足递归式T(n)T(9n/10)+O(n)。由此可得T(n)=O(n)。v例如,将n个输入元素划分成n/5个组,每组5个元素,只可能有一个组不是5个元素。用任意一种排序算法,将每组中的元素

5、排好序,并取出每组的中位数,共n/5个。递归调用Select来找出这n/5个元素的中位数(也就是这些中位数的中位数),若n/5是偶数,则找它的两个中位数中较大的一个,然后以这个元素作为基准划分。v设所有元素互不相同。在这种情况下,找出的基准x至少比3(n-5)/10个元素大,因为在每一组中有2个元素小于本组的中位数,而n/5个中位数中又有(n-5)/10个小于基准x。同理,基准x也至少比3(n-5)/10个元素小。而当n75时,3(n-5)/10n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4 vtemplatevint Partition(Type*a,int p,int r,T

6、ype x)vv int i,left=p,right=r;v Type*b=new Type r-p+1;v for(i=0;i r-p+1;i+)bi=ap+i;v for(i=p;i=r;i+)v v if(bi x)aright-=bi;v v for(i=left;i=right;i+)ai=x;v delete b;return left;vv/找ap.r中第k小的元素返回vtemplatevType Select(Type a,int p,int r,int k)vv int i,j;Type x,t;v if(r-p75)Sort(a,p,r);return ap+k-1;v

7、for(i=0;i=(r-p-4)/5;i+)v v x=ap+5*i至ap+5*i+4的第3小元素;v /将ap+5*i.p+5*i+4的第3小元素与ap+i交换位置v t=ap+i;ap+i=x;x=t;v v /*每一组的中位数排在了ap.p+(r-p-4)/5的位置,现在找中位数的中位数x,r-p-4即上面所说的n-5*/v x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10);v /*将apr中不大于x的放在x左边,比x大的放在x右边,返回中位数的中位数x的下标i*/v i=Partition(a,p,r,x),v j=i-p+1;/求x左边有多少个元素,这些元素

8、都比x小v if(k=j)return Select(a,p,i,k);v else return Select(a,i+1,r,k-j);vv上述算法将每一组的大小定为5,并选取75作为是否作递归调用的分界点。这2点保证了T(n)的递归式中2个自变量之和n/5+3n/4=19n/20=n,01。这是使T(n)=O(n)的关键之处。当然,除了5和75之外,还有其他选择。v设n=r-p+1,即n为输入数组的长度,算法的递归调用在n75时才执行,n75的时候,算法Select所用的计算时间不超过常数C1,找到中位数的中位数x后,算法Select以x为基准调用函数Partition对数组apr进行划

9、分,这需要O(n)时间,算法Select的for循环体执行了n/5次,每一次需要O(1)时间,因此执行for循环共需要O(n)时间。v设对n个元素数组调用Select算法需要T(n)时间,那么找中位数的中位数x至多用了T(n/5)次时间,既然按照基准x划分所得到的两个子数组分别至多3n/4个元素,所以不论对哪一个子数组调用Select算法都至多用了T(3n/4)的时间。v因此,v得到,T(n)=O(n)7575)4/3()5/()(21nnnTnTnCCnT2.10 最接近点对问题最接近点对问题v给定平面上n个点,找出其中一对点,使得在n个点所构成的所有点对中,该点对的距离最小。v最接近点对可

10、能多于一对,简单起见,只考虑找其中的一对作为问题的解。如果我们将每一个点和其他n-1个点的距离算出来,找到最小距离的两个点,算法效率需要O(n2)的计算时间,效率太低。下面设计一个耗时O(nlog2n)的算法:v为了使问题易于理解和分析,先来考虑一维一维的情形。此时,S中的n个点退化为x轴上的n个实数 x1,x2,xn。最接近点对即为这n个实数中相差最小的2个实数。假设我们用x轴上某个点m将S划分为2个子集S1和S2,基于平衡子问题的思想,用S中各点坐标的中位数来作分割点。递归地在S1和S2上找出其最接近点对p1,p2和q1,q2,并设d=min|p1-p2|,|q1-q2|,S中的最接近点对

11、或者是p1,p2,或者是q1,q2,或者是某个p3,q3,其中p3S1且q3S2。v问题在于:能否在线性时间内找到能否在线性时间内找到p3、q3?v如果S的最接近点对是p3,q3,即|p3-q3|d,则p3和q3两者与m的距离不超过d,即p3(m-d,m,q3(m,m+d。由于在S1中,每个长度为d的半闭区间至多包含一个点(否则必有两点距离小于d),并且m是S1和S2的分割点,因此(m-d,m中至多包含S中的一个点。由图可以看出,如果(m-d,m中有S中的点,则此点就是S1中最大点。因此,我们用线性时间就能找到区间(m-d,m和(m,m+d中所有点,即p3和q3。从而我们用线性时间就可以将S1

12、的解和S2的解合并成为S的解。v选取一垂直线l:x=m来作为分割直线。其中m为S中各点x坐标的中位数。由此将S分割为S1和S2。递归地在S1和S2上找出其最小距离d1和d2,并设d=mind1,d2,S中的最接近点对或者是d,或者是某个p,q,其中pP1且qP2。v问题在于:能否在线性时间内找到能否在线性时间内找到p、q?v考虑P1中任意一点p,它若与P2中的点q构成最接近点对的候选者,则必有distance(p,q)d。满足这个条件的P2中的点一定落在一个d2d的矩形R中。由d的意义可知,P2中任何2个S中的点的距离都不小于d。由此可以推出矩形R中最多只有6个S中的点。因此,在分治法的合并步

13、骤中最多只需要检查6n/2=3n个候选者。v证明:证明:将矩形R的长为2d的边3等分,将它的长为d的边2等分,由此导出6个(d/2)(2d/3)的矩形。若矩形R中有多于6个S中的点,由鸽舍原理易知至少有一个(d/2)(2d/3)的小矩形中有2个以上S中的点。设u,v是位于同一小矩形中的2个点,则vdistance(u,v)d,与d的意义矛盾。222223625)3/2()2/()()()()(dddvyuyvxuxv为了确切地知道要检查哪6个点,可将p和P2中所有S2的点投影到垂直线l上。由于能与p点一起构成最接近点对候选者的S2中点一定在矩形R中,所以它们在直线l上的投影点,距离p在l上投影

14、点的距离小于d。由上面的分析可知,这种投影点最多只有6个。因此,若将P1和P2中所有S中点按其y坐标排好序,则对P1中所有点,对排好序的点列作一次扫描,就可以找出所有最接近点对的候选者。对P1中每一点最多只要检查P2中排好序的相继6个点。v下面给出用分治法求二维最接近点对算法:vbool Cpair2(S,&d)vv n=|S|;v if(n 2)return false;v 1、m=S中各点x坐标下标的中位数;v 构造S1和S2,S1=pS|x(p)x(m)v 2、Cpair2(S1,d1);Cpair2(S2,d2);v 3、dm=min(d1,d2);v 4、令P1是S1中距垂直分割线l

15、的距离在dm之内的所有点组成的集合;P2是S2中距分割线l的距离在dm之内所有点组成的集合;v 将P1和P2中的点依其y坐标值排序;并设X和Y是相应的已排好序的点列;第1步:O(n)第3步:O(1)第2步:2T(n/2)第4步:O(nlog2n)第5步:O(n)v 5、通过扫描X以及对于X中每个点检查Y中与其距离在dm之内的所有点(最多6个)可以完成合并;v 当X中的扫描指针逐次向上移动时,Y中的扫描指针可在宽为2dm的区间内移动;v 设dl是按这种扫描方式找到的点对间的最小距离;v 6、d=min(dm,dl);v return true;v v若在每次执行第4步的时候进行排序,则最坏情况下

16、第4步需要O(nlog2n)时间,这不符合要求,需要做一个技术处理。第6步:O(1)v使用预排序技术,在使用分治法之前,预先将S中n个点依其y坐标排好序,设排好序的点为P*,在执行分治法的第4步时,只要对P*进行1次线性扫描,即可抽取出我们所需要排好序的点列X和Y。然后,在第5步中再对X做一次线性扫描,即可求得dl。因此,第4步和第5步两遍扫描合在一起只要用O(n)时间。这样,经过预排序处理后算法后,算法Cpair2所需的计算时间T(n)满足递归方程 v即T(n)=O(nlog2n)。v根据这个思想,写出的程序如下:44)()2/(2)1()(nnnOnTOnTv#include v#incl

17、ude vconst int TOTAL=10000;vusing namespace std;vclass Pointvvpublic:v double getx()const return x;v double gety()const return y;v double setx(double xx)x=xx;return x;v double sety(double yy)y=yy;return y;v virtual bool operator=(Point a)return true;vprotected:v double x,y;v;v/类PointX和PointY分别表示按照x坐

18、标和y坐标排序的点vclass PointX:public Pointvvpublic:v bool operator=(Point a)const return(x=a.getx();v friend inline double distance(const PointX&u,const PointX&v);v;vclass PointY:public Pointvvpublic:v bool operator=(Point a)const return(y=a.gety();v int setp(int pp)p=pp;return p;v int getp()return p;v fri

19、end inline double distance(const PointY&u,const PointY&v);vprivate:v int p;/p表示以x坐标排序时,该点对应的下标(序号)v;vinline double distance(const PointX&u,const PointX&v)vv double dx=u.getx()-v.getx();v double dy=u.gety()-v.gety();v return sqrt(dx*dx+dy*dy);vvinline doulble distance(const PointY&u,const PointY&v)vv

20、 double dx=u.getx()-v.getx();v double dy=u.gety()-v.gety();v return sqrt(dx*dx+dy*dy);vvtemplate vvoid Merge(Type Y,Type Z,int l,int m,int r)vv /将有序的Zl.m与有序的Zm+1.r合并到Yl.rv Type*a=&Zl;Type*b=&Zm+1;Type*c=&Yl;v int anum=m-l+1,ap=0;v int bnum=r-m,bp=0;v int cnum=r-l+1,cp=0;v while(ap anum&bp bnum)v v i

21、f(aap=bbp)ccp+=aap+;v else ccp+=bbp+;v v while(ap anum)ccp+=aap+;v while(bp bnum)ccp+=bbp+;vvtemplate vvoid MergeSort(Type a,int n)vv int anum,bnum,i;Type*b,*c;v if(n=1)return;v anum=n/2;v b=a+anum;bnum=n-anum;v MergeSort(a,anum);v MergeSort(b,bnum);v c=new Typen;v Merge(c,a,0,anum-1,n-1);v for(i=0;

22、in;i+)ai=ci;v delete c;vv/*X存放输入的点集,X和Y分别表示按照x坐标和y坐标排序的点,l和r表示点集Y中成员p的范围*/vvoid closest(PointX X,PointY Y,PointY Z,int l,int r,PointX&a,PointX&b,double&d)vv double d1,d2,d3,dp;int f,g,m,i,j,k;double dr;v PointX ar,br;v if(r-l=1)/2点的情况v v a=Xl;b=Xr;d=distance(Xl,Xr);v return;v v if(r-l=2)/3点的情况v v d1

23、=distance(Xl,Xl+1);d2=distance(Xl+1,Xr);v d3=distance(Xl,Xr);v if(d1=d2&d1=d3)v v a=Xl;b=Xl+1;d=d1;v v else if(d2=d3)v v a=Xl+1;b=Xr;d=d2;v v elsev v a=Xl;b=Xr;d=d3;v v return;v v m=(l+r)/2;/m为点集Y中成员p的范围的中位数 v /*将已经按照y坐标排序的点集Yl.r,等分成两个子集复制到Z,其中Zl.(l+r)/2中的每个点的x坐标都小于Z(l+r)/2+1.r中的每个点的x坐标*/v f=l;g=m+1

24、;v for(i=l;i m)Zg+=Yi;v else Zf+=Yi;v v /递归处理这两个子集(注意参数传递时Z与Y位置的变化)v closest(X,Z,Y,l,m,a,b,d);v closest(X,Z,Y,m+1,r,ar,br,dr);v if(dr d)/d表示这两个子集中各自找到的最近点对的距离较小者v v a=ar;b=br;d=dr;v v Merge(Y,Z,l,m,r);/重构数组Yv /将与分割线距离为d的点置如数组Z中v k=l;v for(i=l;i=r;i+)v v if(fabs(Ym.getx()-Yi.getx()d)Zk+=Yi;v v /搜索Zl.

25、k-1,若其中存在两点的距离小于d,则更新dv for(i=l;ik;i+)v v for(j=i+1;jk&Zj.gety()-Zi.gety()d;j+)v v dp=distance(Zi,Zj);v if(dp d)v v d=dp;a=XZi.getp();b=XZj.getp();v v v vvbool Cpair2(PointX X,int n,PointX&a,PointX&b,double&d)vv int i;PointY*Z,*Y;v if(n 2)return false;v MergeSort(X,n);/将各点按照x坐标排序v Y=new PointYn;v fo

26、r(i=0;in;i+)/将数组X内的信息写入数组Yv v Yi.setp(i);/同一点在数组X中的坐标的下标v Yi.setx(Xi.getx();v Yi.sety(Xi.gety();v v MergeSort(Y,n);/将各点按照y坐标排序v Z=new PointYn;v closest(X,Y,Z,0,n-1,a,b,d);v delete Y;delete Z;return true;vvint main()vv PointX XTOTAL,a,b;v int n=TOTAL;v double d;v int i;v for(i=0;in;i+)v v Xi.setx(dou

27、ble)rand()/100);v Xi.sety(double)rand()/100);v v Cpair2(X,n,a,b,d);v printf(%f,%f)(%f,%f)%fn,a.getx(),a.gety(),b.getx(),b.gety(),d);v return 0;v2.11 循环赛日程问题循环赛日程问题v设有n=2k(k为正整数)个运动员进行乒乓球循环赛正赛,现要求设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次;(2)每个选手一天只能赛一次;(3)循环赛一共进行n-1天。v将比赛日程设计为n行和n-1列的一个表,在表中第i行第j列处填写第i

28、个选手在第j天的对手。v按分治策略,将所有的选手分为两半,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割,直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让这2个选手进行比赛就可以了。v图中所列出的正方形表是8个选手的比赛日程表。其中左上角与左下角的两小块分别为选手1至选手4和选手5至选手8前3天的比赛日程。据此,将左上角小块中的所有数字按其相对位置抄到右下角,又将左下角小块中的所有数字按其相对位置抄到右上角,这样我们就分别安排好了选手1至选手4和选手5至选手8在后4天的比赛日程。依此思想容易将这个比赛日程表推广到具有任意多个选手的情形。

29、该算法没有使用递归,这也说明并非所有的分治策略都要使用递归。123456782143658734127856432187655678123465872143785634128765432112345678以k=3,n=8名选手为例。初始状态:填写第0列。之后,进行k=3个阶段,设第s个阶段要循环ns次,则n1=n/2=4,n2=n1/2=2,n3=n2/2=11221344356657887第1阶段(s=1):填写第1列(j=1)循环4次,循环次数为n1=n/2=4,8个大块,每个大块含m*m=1*1个小块,每次循环复制2个大块,在第t(t=0,1,2,3)次循环时,执行ai+2*t*m-mj

30、=ai+2*t*mj-m和ai+2*t*mj=ai+2*t*m-mj-m,i=1,分别把左下角复制到右上角,把左上角复制到右下角 12342143341243215678658778568765第2阶段(s=2):填写第2,3列(j=2,3)循环2次,循环次数为n2=n1/2=2,4个大块,每个大块含m*m=2*2个小块,每次循环复制2个大块,在第t(t=0,1)次循环时,执行ai+2*t*m-mj=ai+2*t*mj-m和ai+2*t*mj=ai+2*t*m-mj-m,i=2,3,分别把左下角复制到右上角,把左上角复制到右下角 12345678214365873412785643218765

31、56781234658721437856341287654321第3阶段(s=3):填写第4,5,6,7列(j=4,5,6,7)循环1次,循环次数为n3=n2/2=2,2个大块,每个大块含m*m=4*4个小块,每次循环复制2个大块,在第t(t=0)次循环时,执行ai+2*t*m-mj=ai+2*t*mj-m和ai+2*t*mj=ai+2*t*m-mj-m,i=4,5,6,7,分别把左下角复制到右上角,把左上角复制到右下角vvoid Table(int k,int aN)vv int n=1,m=1,i,j,t,s;v for(i=1;i=k;i+)n*=2;v for(i=0;in;i+)v

32、v ai0=i+1;v v /k个阶段,从左到右v for(s=1;s=k;s+)v v n/=2;v /*每个阶段有t次循环,即复制n个大块*/v for(t=0;tn;t+)v v /j表示列v for(j=m;j2*m;j+)v v for(i=m;i2*m;i+)v v ai-m+2*t*mj=ai+2*t*mj-m;/右上角=左下角 v ai+2*t*mj=ai-m+2*t*mj-m;/右下角=左上角v v v v m*=2;v vvvoid Table(int k,int aN)vv int n=1,m=1,i,j,t,s;v for(i=1;i=k;i+)n*=2;v for(i

33、=0;in;i+)v v ai0=i+1;v v for(s=1;s=k;s+)/k个阶段,从左到右v v n/=2;v for(t=0;tn;t+)/每个阶段有t次循环,即复制n个大块v v for(j=m;j2*m;j+)/j表示列v v for(i=m;i2*m;i+)v v ai-m+2*t*mj=ai+2*t*mj-m;/右上角=左下角 v ai+2*t*mj=ai-m+2*t*mj-m;/右下角=左上角v v v v m*=2;v vv循环赛日程安排问题也可以写成递归算法,如下:vvoid table(int x,int k,int*a)vv /此函数为从x号球员起的共2的k次方名球员安排日程表v int i,j,y;v if(k=1)/只有两名球员v v ax0=x;ax1=x+1;v ax+10=x+1;ax+11=x;v v elsev v y=pow(2,k-1);v table(x,k-1,a);v table(x+y,k-1,a);v for(i=x;ix+y;i+)v v for(j=y;j2*y;j+)aij=ai+yj-y;v v for(i=x+y;ix+2*y;i+)v v for(j=y;j2*y;j+)aij=ai-yj-y;v v vv本周课程结束,谢谢!

侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|