算法设计与分析实验指导书.docx

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

算法设计与分析实验指导书.docx

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

算法设计与分析实验指导书.docx

算法设计与分析实验指导书

实验一、求最大公约数

一、实验内容:

(1)至少设计出3种版本的求最大公约数的算法;

(2)对所设计的算法采用大O符号进行时间复杂性分析;

(3)上机实现算法。

二、实验要求:

(1)掌握并应用算法的数学分析和后验分析方法;

(2)理解这样一个观点:

不同的算法能够解决相同的问题,这些算法的解题思路不同,复杂程度不同,解题效率也不同。

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

算法分析

(1)连续整数检测

1.t=min{m,n}

2.m除以t,如果余数为0,则执行步骤3,否则,执行第4步;

3.n除以t,如果余数为0,返回t的值作为结果,否则执行第4步;

4.T=t-1,转第2步。

(2)欧几里得算法

1.r=m%n;

2.循环直到r=0;

2.1m=n;

2.2n=r;

2.3r=m%n;

3.输出n.

(3)分解质因数算法

1.将m分解质因数;

2.将n分解质因数;

3.提取m和n中的公共质因数;

4.将m和n中的公共质因数相乘,乘积作为结果输出

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

实验二、最近对问题

一、实验内容

按照按照蛮力法有关思想,写出相应的程序求解平面上的最近点对,并在计算机上调试成功,并分析其性能特征。

二、实验要求

结合学过的有关算法设计的基本知识,掌握蛮力算法;

理解蛮力算法的概念特征;

掌握其时间性能与空间性能及可能的改进方案。

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

(1)算法分析

用分治算法求S中最接近点对的基本思想是:

选取一垂直线L∶x=m作为分割直线,将S的点分割为点数大致相同的2个子集S1和S2,使得:

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

#include

#include

#include

#include

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

scanf("%lf%lf",&(a[i].x),&(a[i].y));

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

for(i=0;i

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);

scanf("%d",&n);

}

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

returnx1;

elseif(x2

returnx2;

else

returnx3;

}

intm=(p+q)/2;

inti,j,k;

doubled1,d2;

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

if(b[i].index<=m)

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

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

else

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;i<=q;i++)

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

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

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

for(i=p;i

for(j=i+1;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)

{

inti,j,k;

for(i=s,j=m+1,k=s;i<=m&&j<=t;)

{

if(q[i].y>q[j].y)

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

else

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

}

while(i<=m)

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

while(j<=t)

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

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

return0;

}

intcmp_x(constvoid*p,constvoid*q)

{

doubletemp=((Point*)p)->x-((Point*)q)->x;

if(temp>0)

return1;

elseif(fabs(temp)

return0;

else

return-1;

}

intcmp_y(constvoid*p,constvoid*q)

{

doubletemp=((Point*)p)->y-((Point*)q)->y;

if(temp>0)

return1;

elseif(fabs(temp)

return0;

else

return-1;

}

inlinedoublemin(doublep,doubleq)

{

return(p>q)?

(q):

(p);

}

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

 

实验三、快速排序算法

一、实验内容

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

二、实验要求

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

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

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

(1)算法分析

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

对于输入的子序列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]就已排好序。

(2)参考代码

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

if(L.r[i].keyL.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]<->L.r[high];/*将大于区间内最后一个元素的边界下标元素与最后一个元素互换*/

QSort(L,low,ilow-1);

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

QSort(L,ihigh+1,high);

}

voidQuickSort(Sqlist&L)

{

QSort(L,1,L.length);

}

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

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

一、实验内容

编制程序求解如下问题:

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

的最大值(1<=i<=j<=n),当序列中所有整数均为负整数时,其最大子段和为0。

二、实验要求

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

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

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

(1)算法分析

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

如果是,则再看该元素是不是大于0.如果大于0,则问题的解为该元素的值,否则为0;如果输入的数组不是一个数,则求出其数组中间的元素下标。

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

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

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

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

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

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

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

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

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

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

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

(2)参考代码

#include

#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;i<=high;i++){

rightsum+=a[i];

if(rightsum>s2)s2=leftsum;

}

sum=s1+s2;

if(sum

if(sum

}

returnsum;

}

intMaxSum(inta[],intn)

{

returnsubMaxSum(a,0,n-1);

}

voidmain(void){

inti,sum;

inttest[N];

for(i=0;i

printf("pleaseinputthe%dnumber:

",i+1);

scanf("%d",&test[i]);

printf("\n");}

printf("yourinputis:

");

for(i=0;i

printf("%d",test[i]);

printf("\n");

sum=MaxSum(test,N);

printf("themaxsumis:

%d\n",sum);

}

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

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

一、实验内容

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

若给定序列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的最长公共子序列。

二、实验要求

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

初步掌握动态规划算法;

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

(1)算法分析

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

设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

当i,j>0;xi!

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

(2)参考代码

#include"iostream.h"

#include"iomanip.h"

#definemax100

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

{

inti,j,k;

intc[max][max];

for(i=1;i<=m;i++)

{

c[i][0]=0;

}

for(i=1;i<=n;i++)

{

c[0][i]=0;

}

for(i=1;i<=m;i++)

{

for(j=1;j<=n;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];

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

b[k]='|';

}

else

{

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

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

b[k]='-';

}

}

}

}

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<

}

elseif(b[k]=='|')

{

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

}

else

{

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

}

}

voidmain()

{charx[max]={'a','b','c','b','d','a','b'};

chary[max]={'b','d','c','a','b','a'};

intm=7;

intn=6;

charb[max]={0};

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

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

cout<

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

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

一、实验内容

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

二、实验要求

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

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

三、主要仪器设备

装有TC或VisualC++的PC机

四、实验步骤

(1)算法分析

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

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

由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<=j<=n。

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

(2)参考代码

intmaxSum(int[]a)

{intsum=0;

intb=0;

for(inti=0;i

{if(b>0)b+=a[i];

elseb=a[i];

if(b>sum)sum=b;}

returnsum;}

五、注意事项

(1)、将本实验上机调试、运行,注意调试过程中出现的问题;

(2)、结合运行结果,进行复杂性分析。

实验七、哈夫曼编码

一、实验内容

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

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

二、实验要求

了解前缀

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

当前位置:首页 > 求职职场 > 简历

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

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