算法导论实验报告.docx
- 文档编号:24308507
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:73
- 大小:189.95KB
算法导论实验报告.docx
《算法导论实验报告.docx》由会员分享,可在线阅读,更多相关《算法导论实验报告.docx(73页珍藏版)》请在冰豆网上搜索。
算法导论实验报告
实验一快速排序
1.1问题描述
实现对数组的普通快速排序与随机快速排序。
1.2实验要求
(1)实现上述两个算法
(2)统计算法的运行时间
(3)分析性能差异,作出总结
1.3编程环境及语言
编程环境:
Linux
编程语言:
C
1.4实验原理
1.4.1普通排序算法
1)解决排序问题的基本思路:
使用分治法基本步骤:
a.分解:
数组a[low..high]被划分为两个非空子数组a[low..q]和a[q+1..high],使得a[low..q]的每一个元素都小于等于a[q+1..high]的元素。
b.解决:
通过递归调用快速排序对子数组a[low..q]和a[q+1..high]进行排序。
c.合并:
快速排序经过一趟划分操作将数组分解成两个子数组,且位于底部区域的元素均不大于主元,位于顶部区域的元素均不小于主元,所以,一旦两个子数组已经完成分别排序,整个数组自然成为有序序列。
2)快速排序算法:
QuickSort(a,low,high)
1iflow 2thenPartition(a,low,high) 3QuickSort(a,low,q) 4QuickSort(A,q+1,high) 1.4.2随机快速排序算法 在快速排序算法的每一步中,当数组还没有被划分时,可将元素a[p]与a[p..r]中随机选出的一个元素交换后再执PARTITION。 1.4.3随机数生成方法 头文件: #include srand((int)time(NULL));设定随机数种子 rand()%N;产生0-N的随机数。 1.4.4函数运行时间统计方法 gettimeofday()函数 头文件: #include 函数定义: intgettimeofday(structtimeval*tv,struct timezone*tz); 功能描述: gettimeofday()把目前的时间信息存入tv指向的结构体,当地时区信息则放到tz指向的结构体。 intgettimeofday(structtimeval*tv,structtimezone*tz);其中timeval结构定义如下: structtimeval{ time_ttv_sec;/*seconds*/ suseconds_ttv_usec;/*microseconds*/ }; 获取当前时刻,可以精确到微妙级别。 具体该函数在本程序中的应用程序段如下所示: gettimeofday(&start,NULL); QuickSort(a,0,N-1); gettimeofday(&end,NULL); interval=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec); printf("QuickSortinterval=%f",interval/1000.0); printf("\n"); 1.5实验结果 图1快速排序算法部分运行结果截图 表1快速排序算法运行时间统计表(单位: ms) QuickSort 54.462000 54.723000 58.892000 56.450000 55.536000 QuickSort_Random 57.579000 58.233000 57.606000 54.263000 53.250000 △ -3.117000 -3.510000 1.286000 2.187000 2.286000 QuickSort 50.119000 78.724000 53.906000 59.300000 59.701000 QuickSort_Random 55.248000 56.589000 53.940000 58.922000 47.846000 △ -5.129000 22.135000 -0.034000 0.378000 11.855000 1.6结果分析 1)实验数据分析 本实验这设置的随机数组长度为100000,分别统计了10次普通快速排序和随机快速排序的运行时间,如图1所示,其中△值等于QuickSort的运行时间与QuickSort_Random运行时间的差。 不难看出,当△值为正时,QuickSort的运行时间大于QuickSort_Random运行时间,反之,QuickSort_Random运行时间较大。 因为本实验中的快排对象是随机地一组数据,所以△值有正有负是正常的,当快排数据的量越多时,总体上QuickSort的平均运行时间大于QuickSort_Random运行时间。 2)快速排序算法复杂度分析 最坏情况划分: T(n)=T(n-1)+Θ(n)=Θ(n2) 最佳情况划分: T(n)=2T(n/2)+Θ(n)=Θ(nlgn) 随机快速排序在普通开速排序的基础上对主元进行随机选择,减小了排序算法趋于最坏情况的可能性,从某种程度上是对普通快速排序算法的改进。 1.7实验总结 通过本次实验,我对快速排序算法的原理和具体实现有了更深入的认识。 此外,本次试验是我进一步熟悉了Linux环境下的编程方法,熟练掌握了VIM编辑指令,随机数生成方法,函数运行时间统计方法,程序的编译过程,Makefile文件的编写等知识点。 为了养成良好的编程习惯和编码风格,我特地在网上下载并参考了华为的《C语言编程规范》,总之,虽然这次试验花费时间相当长,但是真的收获颇多,如有不尽完善之处还请老师指点,谢谢。 1.8源代码 1.8.1快排源代码 /********************************************************* Corpyrigt@USTC_SSE.2013-2014.Allrightsreserved. Filename: QuickSort.c Author: YuJianID: SG13225026 Version: 1.0Date: 2014/6/21 Description: Thisprogramincludestwokindsofalgorithms, commonquicksortandrandomquicksort History: *********************************************************/ #include #include #include #include #defineN100000 #defineMAX100000 /* *Function: swaptwodatas *Input: &ptr[i],&ptr[low] *Output: NULL *Return: NULL */ voidswap(int*ptr1,int*ptr2){ inttemp; temp=*ptr1; *ptr1=*ptr2; *ptr2=temp; } /* *Function: partitionanarrayintotwopartsbykeyvalue *eachvalueoftheleftsideisgreaterthankeyvalue *eachvalueoftherightsideisoppsite *Input: ptr,low,high *Output: NULL *Return: theposition(i)ofkeyvalueafteronetimepartition */ intPartition(int*ptr,intlow,inthigh){ intkeyvalue; inti,j; i=low; j=high; keyvalue=ptr[i]; while(i! =j){ while(i if(i ptr[i]=ptr[j]; i++; } while(i if(i ptr[j]=ptr[i]; j--; } } ptr[i]=keyvalue; returni; } /* *Function: commonQuickSortalgorithm *ineachpartition,thelowdataisusedaskeyvalue *Input: array(a),low,high *Output: NULL *Return: NULL */ voidQuickSort(int*ptr,intlow,inthigh){ intpstn; if(low pstn=Partition(ptr,low,high); QuickSort(ptr,low,pstn-1); QuickSort(ptr,pstn+1,high); } } /* *Function: QuickSort_Randomalgorithm *ineachpartition,thekeyvalueisselectedfromarrayrandomly *Input: a,low,high *Output: NULL *Return: NULL */ voidQuickSort_Random(int*ptr,intlow,inthigh){ inti; intpstn; if(low i=low+rand()%(high-low+1); swap(&ptr[i],&ptr[low]); QuickSort(ptr,low,high); pstn=Partition(ptr,low,high); QuickSort_Random(ptr,low,pstn-1); } } /* *Function: intmain() *Input: Thedatasofarrayaregeneratedbyfunctionrand() *theintervalofthealgorithms'runningtimeiscounted *byfunctionofgttimeofday() *Output: NULL *Return: 0 */ intmain(){ inti; inta[MAX]; intb[MAX]; structtimevalstart,end; floatinterval; //setradomseedbasedthevalueoftime() srand((unsigned)time(NULL)); for(i=0;i a[i]=rand()%N; b[i]=a[i]; } gettimeofday(&start,NULL); QuickSort(a,0,N-1); gettimeofday(&end,NULL); interval=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec); printf("QuickSortinterval=%f",interval/1000.0); printf("\n"); gettimeofday(&start,NULL); QuickSort_Random(b,0,N-1); gettimeofday(&end,NULL); interval=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec); printf("QuickSort_Randominterval=%f",interval/1000.0); printf("\n"); return0; } 1.8.1快排Makefile #*********************************************************\ #Corpyrigt@USTC_SSE.2013-2014.Allrightsreserved. #Filename: QuickSort.c #Author: YuJianID: SG13225026 #Version: 1.0Date: 2014/6/21 #Description: Thismakefileisusedtocompileandrunthequicksortalgorithm #History: #********************************************************* all: compilerun compile: QuickSort.c gcc-WallQuickSort.c-oQuickSort run: QuickSort ./QuickSort clean: rmQuickSort 实验二背包问题 1.1问题描述 1)0-1背包问题: 给定n种物品和一个背包。 物品i的重量是 ,其价值为 ,背包容量为C。 问应该如何选择装入背包的物品(该物品或被带走,或被留下),使得装入背包中物品的总价值最大? 2)部分背包问题: 场景等与上面问题一样,但选择装入背包的物品可以是物品的一部分,而不必做出0-1的二分选择。 1.2实验要求 (1)实现0-1背包的动态规划算法求解 (2)实现部分背包的贪心算法求解 (3)实现部分背包的动态规划算法求解(选做) 1.3编程环境及语言 编程环境: Linux 编程语言: C 1.4实验原理 1.4.1动态规划原理与分析 动态规划算法的基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 但是经分解得到的子问题往往不是互相独立的。 不同子问题的数目常常只有多项式量级。 如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。 它把已知问题分为很多子问题,按顺序求解子问题,在每一种情况下,列出各种情况的局部解,按条件从中选取那些最有可能产生最佳的结果舍弃其余。 前一子问题为后面子问题提供信息,而减少计算量,最后一个子问题的解即为问题解。 采用此方法求解0-1背包问题的主要步骤如下: ①分析最优解的结构: 最有子结构性质; ②建立递归方程; ③计算最优值; ④构造最优解。 1.4.20-1背包问题的实现 ①最优子结构性质 0-1背包问题具有最优子结构性质。 设(y1,y2…yn)是所给0-1背包问题的一个最优解,则(y2,y3…yn)是下面相应子问题的一个最优解: 因若不然,设(z2,z3…zn)是上述问题的一个最优解,而(y2,y3…yn)不是它的最优解,由此可见 ,且 c。 因此 c 这说明(y1,z2…zn)是所给0-1背包问题的一个更优解,从而(y1,y2…yn)不是所给0-1背包问题的最优解。 此为矛盾。 ②递归关系 设所给0-1背包问题的子问题 的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,……,n时0-1背包问题的最优值。 由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下: 1.4.3贪心算法原理与分析 贪心算法总是作出在当前看来是最好的选择,即贪心算法并不从整体最优解上加以考虑,它所作出的选择只是在某种意义上的局部最优解。 贪心算法不是对所有问题都能得到整体最优解,但对范围相当广的许多问题它能产生整体最优解。 在一些情况下,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好近似解。 贪心算法求解的问题一般具有两个重要性质: 贪心选择性质和最优子结构性质。 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择来达到。 这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。 问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 1.4.4部分背包问题的实现 首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。 若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。 依此策略一直地进行下去,直到背包装满为止。 图1部分背包贪心算法程序流程图 1.5实验结果 1.5.10-1背包问题动态规划算法运行结果 1.5.2部分背包问题贪心算法运行结果 1.6结果分析 1)0-1背包结果分析 在0-1背包问题问题中,我们输入3个物品,分别为(3,4),(4,5)和(5,6),当背包允许的最大容量为10时,最多只能放入(4,5)和(5,6),最大价值为11,结果正确。 1)部分背包结果分析 在0-1背包问题问题中,我们也输入3个物品,分别为(3,4),(4,5)和(5,6),他们的价值比率分别为4/3,5/4和6/5,按照贪心算法原则,先放入比率最大的物品即(3,4),再放入物品(4,5),这是剩余容量为3,在用第三种物品将其填满,此时总价值为4+5+3*(6/5)=12.6,所以结果也是正确的。 1.7实验总结 通本次实验我动态规划方法和贪心算法有了更深入的认识,实现了对背包问题的编程和运行。 对于0-1背包问题,贪心选择之所以不能得到最优解是因为在这种情况下,它无法保证最终能将背包装满,部分闲置的背包空间使每公斤背包空间的价值降低了。 事实上,在考虑0-1背包问题时,应比较选择该物品和不选择该物品所导致的最终方案,然后再作出最好选择。 由此就导出许多互相重叠的子问题。 这正是该问题可用动态规划算法求解的另一重要特征。 选取最优的量度标准实为用贪心方法求解问题的核心。 1.8源代码 1.8.10-1背包问题源代码 /********************************************************* Corpyrigt@USTC_SSE.2013-2014.Allrightsreserved. Filename: .c Author: YuJianID: SG13225026 Version: 1.0Date: 2014/6/21 Description: Thisprogramisusedtosolvethe0-1knapsack problembyDynamicProgramming History: *********************************************************/ #include #defineMAX_NUMBER10 #defineMAX_VALUE100 intc[MAX_NUMBER][MAX_VALUE]; /* *Function: intKnapsack_Dynamic(intm,intn) *Input: thecapacityofknapsackm,thenumberofgoodsn *Output: themaxmunvalueinknapsack *Return: c[n][m] */ intKnapsack_Dynamic(intm,intn){ inti,j; intw[MAX_NUMBER],v[MAX_NUMBER]; printf("Inputeachgoods'weightandvalue: \n"); for(i=1;i<=n;i++){ scanf("%d,%d",&w[i],&v[i]); } for(i=0;i for(j=0;j c[i][j]=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++){ //ifcurrentgoodscapacityislessthantheknapsack'scapacity if(w[i]<=j){ //ifthecurrentvalueaddsthegoodsvalueofsparespace //intheknapsackisgreaterthantheformerselectioncase, //thenupdatec[i][j] if((v[i]+c[i-1][j-w[i]])>c[i-1][j]){ c[i][j]=v[i]+c[i-1][j-w[i]]; } else c[i][j]=c[i-1][j]; } else c[i][j]=c[i-1][j]; } returnc[n][m]; } /* *Function: intmain *Input: m,n *Output: themaximumvalueofknapsack *Return: 0 */ intmain(){ intm,n; //inti,j; printf("\n----DynamicProgrammingfor0-1Knapsackproblem-----\n\n"); printf("Inputtheknapsack'scapacityandthenu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 导论 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)