算法设计与分析实验指导书Word文档下载推荐.docx

上传人:b****4 文档编号:17840283 上传时间:2022-12-11 格式:DOCX 页数:38 大小:32.72KB
下载 相关 举报
算法设计与分析实验指导书Word文档下载推荐.docx_第1页
第1页 / 共38页
算法设计与分析实验指导书Word文档下载推荐.docx_第2页
第2页 / 共38页
算法设计与分析实验指导书Word文档下载推荐.docx_第3页
第3页 / 共38页
算法设计与分析实验指导书Word文档下载推荐.docx_第4页
第4页 / 共38页
算法设计与分析实验指导书Word文档下载推荐.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

算法设计与分析实验指导书Word文档下载推荐.docx

《算法设计与分析实验指导书Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验指导书Word文档下载推荐.docx(38页珍藏版)》请在冰豆网上搜索。

算法设计与分析实验指导书Word文档下载推荐.docx

S1={p∈S|p(x)≤m},S2={p∈S|p(x)>

m}

其中:

m是S中各点x坐标的中位数,因此S1和S2中点数大致相同,且S=S1∪S2。

递归地在S1和S2上解最接近点对的问题,分别得到S1和S2中的最小距离d1和d2,并设d=min{d1,d2}。

用P1和P2分别表示在直线L左边和右边与其距离在d范围的点构成的两个垂直长条平面区域。

P1:

{p∈P1|(|m-x(p)|≤d)},P2:

{p∈P2|(|x(p)-m|≤d)}

S中的最接近点对的距离或者是d,或者是某个{p,q}点对的距离,其中p∈P1,q∈P2。

如果{p,q}是S中的最接近点对,则必有distance(p,q)  将上述描述简化如下:

(1)递归用L将节点集分成两个相等的部分;

(2)设d是d1和d2的最小值;

(3)删除离L超过d的节点;

(4)按照y维扫描剩下的节点,计算5个邻居的距离;

(5)如果距离小于d,更新d

下面我们分析分治算法的时间复杂度,由于步骤2-5是每个递归过程中都要去做的,我们先分析2-5。

步骤2时间复杂度为O

(1);

步骤3时间复杂度为O(n);

步骤4时间复杂度为O

(1);

步骤5时间复杂度为O

(1),所以步骤2-5的时间复杂度为O(n)。

步骤1递归地将平面S中的点分成两个相等的部分时间复杂度为O(logn),所以总的时间复杂度为O(n)*O(logn)=O(nlogn)。

(2)参考代码

#include<

iostream>

#include<

cmath>

cstdio>

cstdlib>

cstring>

usingnamespacestd;

constintN=100005;

constdoubleMAX=10e100;

constdoubleeps=0.00001;

typedefstructTYPE

{

doublex,y;

intindex;

}Point;

Pointa[N],b[N],c[N];

doubleclosest(Point*,Point*,Point*,int,int);

doubledis(Point,Point);

intcmp_x(constvoid*,constvoid*);

intcmp_y(constvoid*,constvoid*);

intmerge(Point*,Point*,int,int,int);

inlinedoublemin(double,double);

intmain()

intn,i;

doubled;

scanf("

%d"

&

n);

while(n)

{

for(i=0;

i<

n;

i++)

%lf%lf"

(a[i].x),&

(a[i].y));

qsort(a,n,sizeof(a[0]),cmp_x);

a[i].index=i;

memcpy(b,a,n*sizeof(a[0]));

qsort(b,n,sizeof(b[0]),cmp_y);

d=closest(a,b,c,0,n-1);

printf("

%.2lf\n"

d);

}

return0;

}

doubleclosest(Pointa[],Pointb[],Pointc[],intp,intq)

if(q-p==1)

returndis(a[p],a[q]);

if(q-p==2)

doublex1=dis(a[p],a[q]);

doublex2=dis(a[p+1],a[q]);

doublex3=dis(a[p],a[p+1]);

if(x1<

x2&

&

x1<

x3)

returnx1;

elseif(x2<

returnx2;

else

returnx3;

intm=(p+q)/2;

inti,j,k;

doubled1,d2;

for(i=p,j=p,k=m+1;

=q;

if(b[i].index<

=m)

c[j++]=b[i];

//数组c左半部保存划分后左部的点,且对y是有序的.

c[k++]=b[i];

d1=closest(a,c,b,p,m);

d2=closest(a,c,b,m+1,q);

doubledm=min(d1,d2);

merge(b,c,p,m,q);

//数组c左右部分分别是对y坐标有序的,将其合并到b.

for(i=p,k=p;

if(fabs(b[i].x-b[m].x)<

dm)

//找出离划分基准左右不超过dm的部分,且仍然对y坐标有序.

for(i=p;

k;

for(j=i+1;

j<

k&

c[j].y-c[i].y<

dm;

j++)

doubletemp=dis(c[i],c[j]);

if(temp<

dm=temp;

}returndm;

doubledis(Pointp,Pointq)

doublex1=p.x-q.x,y1=p.y-q.y;

returnsqrt(x1*x1+y1*y1);

intmerge(Pointp[],Pointq[],ints,intm,intt)

for(i=s,j=m+1,k=s;

=m&

=t;

if(q[i].y>

q[j].y)

p[k++]=q[j],j++;

p[k++]=q[i],i++;

while(i<

p[k++]=q[i++];

while(j<

=t)

p[k++]=q[j++];

memcpy(q+s,p+s,(t-s+1)*sizeof(p[0]));

intcmp_x(constvoid*p,constvoid*q)

doubletemp=((Point*)p)->

x-((Point*)q)->

x;

if(temp>

0)

return1;

elseif(fabs(temp)<

eps)

return-1;

intcmp_y(constvoid*p,constvoid*q)

y-((Point*)q)->

y;

inlinedoublemin(doublep,doubleq)

return(p>

q)?

(q):

(p);

 

实验三、快速排序算法

利用快速排序算法编制程序对给定的一组数排序,并分析其性能。

掌握分治法解决问题的策略;

学会使用分治法设计程序并能分析它。

快速排序的基本思想是基于分治策略的。

对于输入的子序列L[p..r],如果规模足够小则直接进行排序,否则分三步处理:

分解(Divide):

将输入的序列L[p..r]划分成两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。

递归求解(Conquer):

通过递归调用快速排序算法分别对L[p..q]和L[q+1..r]进行排序。

合并(Merge):

由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序。

QSort(Sqlist&

L,intlow,inthigh){

c=high-low;

/*循环次数*/

if(c<

10)直接调用插入排序法;

/*小数时直接调用插入排序法*/

if(L.r[low].key>

L.r[high].key)L.r[low]<

->

L.r[high];

/*确保区间内第一个元素的值不大于区间内最后一个元素的值*/

ilow=low;

/*小于区间内第一个元素的值数组边界下标*/

ihigh=high;

/*大于区间内最后一个元素的值数组边界下标*/

for(i=low+1;

i<

c;

i++){

if(L.r[i].key<

L.r[low].key)L.r[i]<

L.r[++ilow];

/*小于区间内第一个元素的值放置ilow区间内*/

else

if(L.r[i].key>

L.r[high].key){

L.r[i]<

L.r[--ihigh];

/*大于区间内最后一个元素的值放置ihigh区间内*/

i--;

/*下一个比较位置不变*/

c--;

/*循环次数减一*/

}

L.r[ilow]<

L.r[low];

/*将小于区间内第一个元素的边界下标元素与第一个元素互换*/

L.r[ihigh]<

/*将大于区间内最后一个元素的边界下标元素与最后一个元素互换*/

QSort(L,low,ilow-1);

QSort(L,ilow+1,ihigh-1);

QSort(L,ihigh+1,high);

voidQuickSort(Sqlist&

L)

{

QSort(L,1,L.length);

实验四、最大子段和(分治法)

编制程序求解如下问题:

给定由n个整数(可能有负整数)组成的序列(a1,a2,…,an),最大子段和问题要求该序列形如

的最大值(1<

=i<

=j<

=n),当序列中所有整数均为负整数时,其最大子段和为0。

进一步掌握递归算法的设计思想以及递归程序的调式技术;

理解这样一个观点,分治与递归经常同时应用在算法设计之中。

首先判断输入的数组是不是一个元素。

如果是,则再看该元素是不是大于0.如果大于0,则问题的解为该元素的值,否则为0;

如果输入的数组不是一个数,则求出其数组中间的元素下标。

递推对前半部分数组(low,center)和后半部分(center+1,high)求最大字段和.之后,设置一个左标记和一个右标记。

从数组中间向前边执行for语句。

在这个过程中,把当前元素加到左标记里面去。

同时判断左标记是不是大于左部分可能的字段和,如果大于,把左部分可能的字段和值设置为左标记的值。

对数组的右半部分做同样操作。

把右半部分的当前元素加到右标记里面去。

同时判断右标记是不是大于右部分可能的字段和,如果大于,把右部分可能的字段和值设置为右标记的值。

之后设置可能的问题解为左部分可能解和右部分可能解之和。

之后判断该可能解是不是大于该数组左边和右边的递推解。

如果前者没有后面2者的一个大。

则设置问题的最终解为最大者。

stdio.h>

#defineN10

intsubMaxSum(inta[],intlow,inthigh)/*quickSort*/

intsum=0;

inti;

if(low==high){

sum=a[low];

if(sum<

0)

sum=0;

else{

intcenter=(low+high)/2;

ints1=0;

intleftsum=0;

intrightsum=0;

ints2=0;

leftsum=subMaxSum(a,low,center);

rightsum=subMaxSum(a,center+1,high);

for(i=center;

i>

=low;

i--){

leftsum+=a[i];

if(leftsum>

s1)s1=leftsum;

for(i=center+1;

=high;

i++){

rightsum+=a[i];

if(rightsum>

s2)s2=leftsum;

sum=s1+s2;

leftsum)sum=leftsum;

rightsum)sum=rightsum;

returnsum;

intMaxSum(inta[],intn)

returnsubMaxSum(a,0,n-1);

voidmain(void){

inti,sum;

inttest[N];

for(i=0;

N;

pleaseinputthe%dnumber:

"

i+1);

&

test[i]);

\n"

);

yourinputis:

i++)

%d"

test[i]);

sum=MaxSum(test,N);

themaxsumis:

%d\n"

sum);

实验五、最长公共子序列问题

利用动态规划算法编制程序求解下面的问题:

若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:

zj=xij。

例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

熟悉最长公共子序列问题的算法;

初步掌握动态规划算法;

最长公共子序列问题具有最优子结构性质。

设X={x1,...,xm},Y={y1,...,yn},及它们的最长子序列Z={z1,...,zk},则:

1、若xm=yn,则zk=xm=yn,且Z[k-1]是X[m-1]和Y[n-1]的最长公共子序列

2、若xm!

=yn,且zk!

=xm,则Z是X[m-1]和Y的最长公共子序列

3、若xm!

=yn,且zk!

=yn,则Z是Y[n-1]和X的最长公共子序列

由性质导出子问题的递归结构

当i=0,j=0时,c[i][j]=0

当i,j>

0;

xi=yi时,c[i][j]=c[i-1][j-1]+1

xi!

=yi时,c[i][j]=max{c[i][j-1],c[i-1][j]}

#include"

iostream.h"

iomanip.h"

#definemax100

voidLCSLength(intm,intn,char*x,char*y,char*b)

inti,j,k;

intc[max][max];

for(i=1;

=m;

i++)

c[i][0]=0;

=n;

c[0][i]=0;

for(j=1;

j++)

if(x[i-1]==y[j-1])

c[i][j]=c[i-1][j-1]+1;

k=i*(n+1)+j;

b[k]='

\\'

;

elseif(c[i-1][j]>

=c[i][j-1])

c[i][j]=c[i-1][j];

|'

else

c[i][j]=c[i][j-1];

-'

voidLCS(inti,intj,char*x,char*b,intwidth)

if(i==0||j==0)

return;

intk=i*(width+1)+j;

if(b[k]=='

LCS(i-1,j-1,x,b,width);

cout<

<

x[i]<

endl;

elseif(b[k]=='

LCS(i-1,j,x,b,width);

LCS(i,j-1,x,b,width);

voidmain()

{charx[max]={'

a'

'

b'

c'

d'

};

chary[max]={'

intm=7;

intn=6;

charb[max]={0};

LCSLength(m,n,x,y,b);

LCS(m,n,x,b,n);

endl<

实验六、最大子段和(动态规划)

运用动态规划法编制一个程序求解实验3的最大字段和问题,并对这两种算法比较分析。

深刻掌握动态规划法的设计思想并能熟悉运用;

理解这样一个观点,同样的问题可以用不同的方法解决,一个好的算法是返回努力和重新修正的结果。

若记b[j]=max(a[i]+a[i+1]+..+a[j]),其中1<

=j,并且1<

=n。

则所求的最大子段和为maxb[j],1<

由b[j]的定义可易知,当b[j-1]>

0时b[j]=b[j-1]+a[j],否则b[j]=a[j]。

故b[j]的动态规划递归式为:

b[j]=max(b[j-1]+a[j],a[j]),1<

据此,可设计出求最大子段和问题的动态规划算法。

intmaxSum(int[]a)

{intsum=0;

intb=0;

for(inti=0;

a.length;

{if(b>

0)b+=a[i];

elseb=a[i];

if(b>

sum)sum=b;

returnsum;

实验七、哈夫曼编码

运用贪心法编制程序求解如下问题:

设需要编码的字符集为{d1,d2,…dn},它们出现的频率为{w1,w2,…wn},应用哈夫曼树构造最短的不等长编码方案。

了解前缀

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 交通运输

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1