算法分析与设计实验报告MicrosoftWord文档.docx
- 文档编号:28589647
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:28
- 大小:64.47KB
算法分析与设计实验报告MicrosoftWord文档.docx
《算法分析与设计实验报告MicrosoftWord文档.docx》由会员分享,可在线阅读,更多相关《算法分析与设计实验报告MicrosoftWord文档.docx(28页珍藏版)》请在冰豆网上搜索。
算法分析与设计实验报告MicrosoftWord文档
MMMM大学计算机科学系
实验报告书
课程名:
《算法分析与设计》
班级:
计科系0802
学号:
2008210707
姓名:
xxxxxx
指导老师:
xxxx
提交日期:
2010-11-23
目录:
实验三·······················3——6
实验五·······················7——9
实验六·······················10——12
实验七·······················13——16
实验八·······················17——18
说明:
单元实验报告包含五个内容
A.实验题目
B.实验目的
C.实验要求
D.程序代码及运行结果(分割为两面)
E.心得体会
程序代码实现语言:
C++
编程工具:
visualC++
实验三
实验项目———串匹配问题
1.实验题目
给定一个文本,在该文本中查找并定位任意给定的字符串
2.实验目的
(1)深刻理解并掌握蛮力法的设计思想;
(2)提高应用蛮力法设计算法的技能;
(3)理解这样一个观点:
用蛮力法设计的算法,一般来说,经过适度的努力后,都可以对算法的第一个版本进行一定程度的改良,改进其时间性能。
3.实验要求
(1)实现BF算法;
(2)实现BF算法的改进算法:
KMP算法和BM算法;
(3)对上述三个算法进行时间复杂性分析,并设计实验程序验证分析结果。
4.程序代码及对应运行结果
(1)BF算法
#include
usingnamespacestd;
intBF(char*text,char*pattern)
{
inti,j;//分别指向每一个S和T的字符
for(i=0;i { for(j=0;j { if(text[i+j]==pattern[j]) j++; else break;//匹配失败跳出进行下一趟匹配 } if(j==strlen(pattern))//匹配成功调处外层循环 break; } if(j==strlen(pattern))//匹配成功返回主串下标 returni; else return-1;//匹配失败返回-1 } voidmain() { char*Text="aaaadddddd"; char*Pattern="uaadd"; ints=BF(Text,Pattern); cout< } (2)KMP算法 #include #include voidget_nextval(constchar*T,intnext[]); intKMP(constchar*Text,constchar*Pattern)//const表示函数内部不会改变这个参数的值。 { if(! Text||! Pattern||Pattern[0]=='\0'||Text[0]=='\0')// return-1;//空指针或空串,返回-1。 intlen=0; constchar*c=Pattern; while(*c++! ='\0')//移动指针比移动下标快。 { ++len;//字符串长度。 } int*next=newint[len+1]; get_nextval(Pattern,next);//求Pattern的next函数值 intindex=0,i=0,j=0; while(Text[i]! ='\0'&&Pattern[j]! ='\0') { if(Text[i]==Pattern[j]) { ++i;//继续比较后继字符 ++j; } else { index+=j-next[j]; if(next[j]! =-1) j=next[j];//模式串向右移动 else { j=0; ++i; } } }//while delete[]next; if(Pattern[j]=='\0') returnindex;//匹配成功 else return-1; } intmain()//abCabCad { char*text="aaaadddddddddddddd"; char*pattern="addd"; //getNext(pattern,n); //get_nextval(pattern,n); cout< return0; } voidget_nextval(constchar*T,intnext[]) { //求模式串T的next函数值并存入数组next。 intj=0,k=-1; next[0]=-1; while(T[j/*+1*/]! ='\0') { if(k==-1||T[j]==T[k]) { ++j;++k; if(T[j]! =T[k]) next[j]=k; else next[j]=next[k]; }//if else k=next[k]; }//while }//get_nextval (3)BM算法 #include usingnamespacestd; intDist(char*t,charch) {intlen=strlen(t); inti=len-1; if(ch==t[i]) returnlen; i--; while(i>=0) { if(ch==t[i]) returnlen-1-i; else i--; } returnlen; } intBM(char*s,char*t) { intn=strlen(s); intm=strlen(t); inti=m-1; intj=m-1; while(j>=0&&i { if(s[i]==t[j]) { i--; j--; } else { i+=Dist(t,s[i]); j=m-1; } } if(j<0) { returni+1; } return-1; } voidmain() { char*s="aaaaddddd"; char*t="aadd"; Dist(t,'\0'); intk=BM(s,t); cout< } 五.我的感想 首先三个看似简单的算法确实花费了我好多时间,一方面想把它们完全掌握,两一方面却碰到了重重难题。 难题之一是关于后两个算法的理解,花了相当的功夫在上面再加上很多次的失败,最后总算是弄明白了。 然后又是关于匹配串的最后得字符的设置,很难把握最后得那个字符的下标到底是‘\0’对应的下标,或者是j==strlen(t);这也让我苦思冥想了好久,最后发现在用字符数组解决这样的问题的时候总是会有这样令人头疼的问题,所以干脆弃之用指针指向指定字符串,这样做起来更容易理解一点。 做BF算法的时候并不是想象当中的“直接基于问题描述编写代码”那样的easy,在写的时候同样遇到了死循环这种情况,困惑了良久,最后发现问题的本质还是在于对字符数组的使用上面,所以最后三个实验都用了指针! 做完这三个实验,心里舒服了好多,毕竟对我这个基本功本来就不够的人来说,这已是很大的进步了,我要继续努力,坚持把剩下的实验做完做好彻底的弄明白! 实验五 实验项目————8枚硬币问题 1.实验题目 在8枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。 可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测出这枚假币。 2.实验目的 (1)深刻理解并掌握减治法的设计思想; (2)提高应用减治法设计算法的技能; (3)理解这样一个观点: 建立真确的模型对问题的求解时非常重要的。 3.实验要求 (1)设计减治法实现8枚硬币问题; (2)设计实验程序,考察用减治技术设计的算法是否高效; (3)扩展算法,使之能处理N枚硬币中有一枚假币的问题。 4.程序代码 #include usingnamespacestd; voidreduce_m(intcoin[],intlow,inttop) { if(low==top) { Cout<<"假币的序号为,”< } elseif(low-top==1) //总数为2无法判断 { Cout<<"无法判断"< } elseif(low { inttemp=(top-low+1)/3; intsum1=0,sum2=0; for(inti=0;i { sum1+=coin[low+i]; sum2+=coin[top-i]; } if(sum1==sum2)//在中间 { reduce_m(coin,low+temp,top-temp); } else//在两边,不在中间 { if(sum1==coin[low+temp]*temp)//左边的和中间的相等,在右边 { reduce_m(coin,top-temp+1,top); } else { reduce_m(coin,low,plow+temp-1); } } } } voidmain() { intcoin[]={1,1,1,1,8,1,1,1,1,1,1,1,1}; reduce_m(coin,0,sizeof(coin)/sizeof(coin[0])-1); } 5.心得体会 仅仅解决八枚硬币问题并用不着花费太多的时间精力,若是不加考虑算法的时间复杂性,直接用IF—else语句就可以进行判断,但是当要用到减治法时就不那么easy了。 首先在设计减治法的时候,一直困扰我的是若何设计算法开头,才能使后面的部分很好的实现对其本身的递归调用,这个问题纯粹是对递归的研究,我看了好几个用递归实现的算法,但是设计的算法还是不够清晰,而且还是对某些最坏情况不能运行,这让我很苦恼,原以为一切已经OK,出现这样的结果令我心灰意冷! ! 良久,想到上网查找,于是参考了网上的相关资料弄出来了上面这样的算法,虽然都某些部位至今还是有些模糊,但是对我来说,这已经是又一次的突破了。 我领悟到分治技术和减值技术对递归技术的依赖,要掌握好分治技术和减值技术,必须的有很好的递归算法设计能力! 我也算见识了这三者的本质关系! 实验六 实验项目————最大字段核问题 1.实验题目 给定N个整数(可能有负数)组成的序列(a1,a2,···an),求该序列形如的字段和的最大值,当所有整数都为负数时,其最大字段和为0。 . 2. 实验目的 (1)深刻掌握动态规划法的设计思想并能熟练运用; (2)理解这样一个观点: 同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修订的结果。 3.实验要求 (1)分别用蛮力法、分治法和动态规划法设计最大字段和问题的算法; (2)比较不同算法的时间性能; (3)给出测试数据,写出程序文档。 4.程序代码 (1)蛮力法 #include usingnamespacestd; intMax_bf(inta[],intn) { inti (1),j,max=a[0],sum=a[0],max1=0;intt(0); while(t while(i sum=0; for(j=t;j sum+=a[j]; if(max max=sum; i++; } if(max1 max1=max; t++; } returnmax1; } voidmain() { intb[]={1,2,3,4,-1,-3,4,-2,5,2,6}; cout< } (2)分治法 #include usingnamespacestd; intMaxsum(inta[],intlow,inttop) { intsum=0; intleftsum,rightsum,mid; if(low==top){//序列长度为一直接求解 if(a[low]>0) sum=a[low]; elsesum=0; } else{ mid=(low+top)/2;//划分 leftsum=Maxsum(a,low,mid);//对应情况一递归求解 rightsum=Maxsum(a,mid+1,top);//对应情况二递归求解 ints1=0,lefts=0;//情况三,先求解si for(inti=mid;i>=low;i--) { lefts+=a[i]; if(s1 s1=lefts; } ints2=0,rights=0;//再求解s2 for(intj=mid+1;j<=top;j++) { rights+=a[j]; if(s2 s2=rights; } sum=s1+s2;//计算情况三的最大字段和 if(sum if(sum } returnsum; } voidmain() { intb[]={-3,-3,6,6,-9,5,6}; cout< } (3)动态规划法 #include usingnamespacestd; intmaxSum(inta[],intn) { intsum=0; intb=0; for(inti=0;i { if(b>0) { b+=a[i]; } else { b=a[i]; } if(sum0) sum=b; } returnsum; } voidmain() { inttarry[]={-3,5,4,6,-9,-4,9,4,8}; intt=sizeof(tarry)/sizeof(tarry[0]); cout< } 5.心得体会 虽然蛮力法的设计理论上说是最为直接的、最容易实现的算法,但是在关于最大字段问题的设计中,我感觉到了设计蛮力法中,嵌套循环的设计很让人难以完全掌控其工作流程。 对于第二个算法,用分治法实现最大字段问题的解决中,我觉得难点还在对递归思想的理解和设计上,这个程序我最是很难做到完全由自己设计,因为对递归的整个过程总是不那么明晰,很模糊。 对一个设计好了的递归算法看得明白,对其思路也可以很清晰地领悟,但就是无法独立设计出一个完整的嵌有递归思路的算法。 最后的动态规划法,虽然我的对于最大字段问题的解决算法边写出来了,但是我对前面的最优性原理还是掌握的不够充分,对具体的问题很难把握是不是应当用动态规划法来求解;而且我的关于最大子段和问题的算法设计也是根据课本相关章节的提示设计的,所以我想在对前面的理论部分的知识再加深一下学习! 实验七 实验项目————霍夫曼编码 1.实验题目 设需要编码的字符集为{},它们出现的频率为{},应用霍夫曼树构造最短的不等长的编码方案。 2.实验目的 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最有子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用。 3.实验要求 (1)证明霍夫曼树满足最有子结构性质; (2)设计贪心算法求解霍夫曼编码方案; (3)设计测试数据,写出程序结构。 4.程序代码 #include #include #include typedefstruct { unsignedintweight; //用来存放各个结点的权值 unsignedintparent,LChild,RChild; //指向双亲、孩子结点的指针 }HTNode,*HuffmanTree; //动态分配数组,存储哈夫曼树 typedefchar*HuffmanCode; //动态分配数组,存储哈夫曼编码 //选择两个parent为0,且weight最小的结点s1和s2 voidSelect(HuffmanTree*ht,intn,int*s1,int*s2) { inti,min; for(i=1;i<=n;i++) { if((*ht)[i].parent==0) { min=i; break; } } for(i=1;i<=n;i++) { if((*ht)[i].parent==0) { if((*ht)[i].weight<(*ht)[min].weight) min=i; } } *s1=min; for(i=1;i<=n;i++) { if((*ht)[i].parent==0&&i! =(*s1)) { min=i; break; } } for(i=1;i<=n;i++) { if((*ht)[i].parent==0&&i! =(*s1)) { if((*ht)[i].weight<(*ht)[min].weight) min=i; } } *s2=min; } //构造哈夫曼树ht,w存放已知的n个权值 voidCrtHuffmanTree(HuffmanTree*ht,int*w,intn) { intm,i,s1,s2; m=2*n-1;//总共的结点数 *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(i=1;i<=n;i++)//1--n号存放叶子结点,初始化 { (*ht)[i].weight=w[i]; (*ht)[i].LChild=0; (*ht)[i].parent=0; (*ht)[i].RChild=0; } for(i=n+1;i<=m;i++)//非叶子结点的初始化 { (*ht)[i].weight=0; (*ht)[i].LChild=0; (*ht)[i].parent=0; (*ht)[i].RChild=0; } printf("\n哈夫曼树为: \n"); for(i=n+1;i<=m;i++)//创建非叶子结点,建哈夫曼树 {//在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2 Select(ht,i-1,&s1,&s2); (*ht)[s1].parent=i; (*ht)[s2].parent=i; (*ht)[i].LChild=s1; (*ht)[i].RChild=s2; (*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight; printf("%d(%d,%d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight); } printf("\n"); } //从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码 voidCrtHuffmanCode(HuffmanTree*ht,HuffmanCode*hc,intn) { char*cd;//定义的存放编码的空间 inta[100]; inti,start,p,w=0; unsignedintc; hc=(HuffmanCode*)malloc((n+1)*sizeof(char*)); //分配n个编码的头指针 cd=(char*)malloc(n*sizeof(char)); //分配求当前编码的工作空间 cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符 for(i=1;i<=n;i++) //求n个叶子结点对应的哈夫曼编码 { a[i]=0; start=n-1;//起始指针位置在最右边 for(c=i,p=(*ht)[i].parent;p! =0;c=p,p=(*ht)[p].parent) //从叶子到根结点求编码 { if((*ht)[p].LChild==c) { cd[--start]='1';//左分支标1 a[i]++; } else { cd[--start]='0';//右分支标0 a[i]++; } } hc[i]=(char*)malloc((n-start)*sizeof(char)); //为第i个编码分配空间 strcpy(hc[i],&cd[start]);//将cd复制编码到hc } free(cd); for(i=1;i<=n;i++) printf("权值为
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 分析 设计 实验 报告 MicrosoftWord 文档