1、08计科2班王进 12号 (上机实验报告) 姓名: 王 进 班级: 08 计科(2)班 学号: 080104021112 指导老师:秦明 完成时间:2011年5月12日星期四一题目:归并排序二算法介绍归并排序采用的是分治法。分治策略是将两个已排好序的集合归并成一个新的已排好序的集合。归并排序分两步走:1、划分元素。2、归并。这里是2路归并排序,即:假设初始序列含有n个记录,这些记录可划分成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列;再两两归并如此重复,直至得到一个长度为n的有序序列为止。即为2路归并排序。三程序流程图开始开始int low, mi
2、d, high输入数据退出Lowhigh?归并排序 meresort(int low ,int hing ) N mid=(low+high)/2mergsort(low,high)mergesort(mid+1,high)打印排序结果K=1,J1=1 Y结束meresort(int low ,int hing )K=1,J1=1打印排序结果K=1,J1=1四源程序及实验结果#include #define N 10void merge(int a,int b,int low,int mid,int high) int h,i,j,k; h=low,i=low,j=mid+1; while(h
3、=mid&j=high) if(ahmid) for(k=j;k=high;k+) bi=ak; i+; else for(k=h;k=mid;k+) bi=ak; i+; for(k=low;k=high;k+) ak=bk; for(int i=0;i10;i+) printf(%d ,ai);printf(nn); void mergesort(int a,int b,int low,int high) int mid; if(lowhigh) mid=(low+high)/2; mergesort(a,b,low,mid); mergesort(a,b,mid+1,high); mer
4、ge(a,b,low,mid,high); void main() int aN;/310,285,179,652,351,423,861,254,450,520;int bN;int i;printf(输入数组中待排序的数:n);for(i=0;iN;i+)scanf(%d,&ai);printf(n);mergesort(a,b,0,9); 结果截图五 结果分析实验采用二路归并的策越,先左子树后右子树,先将元素划分知道成最小的单元然后合并。第一次归并310,285归并成了285,310,第二次归并,285,310,179归并成了179,285,310,直到形成最终的结果,左边归并好了归并右
5、边这样就有了两个各含5个元素的已分好类的子集合,最后的归并得到分好类的结果 时间复杂度:n个元素进行归并排序,共需 logn ,每次所需比较关键字的次数不超过n, 共比较O(nlogn)次。每趟移动n个记录, 共移动O(nlogn)个记录。归并排序需要一个大小为n的辅助空间b1.n。归并排序是稳定的。一题目:快速排序二 、算法介绍快速排序的分治策略每次确定每个元素在排好序后的数组的位置。通过分支策略找到划分元素在排好序后的数组中应该出现的位置。让后以这个找到的元素为划分点,分成左右两支,这样依次下去形成最终的结果。三 、程序流程图开始退出NpY int v,i,tempv=am,i=mi=i+
6、1Y aiv Nip Ytemp=aiai=ap,ap=temp 结束四 、源程序及实验结果#include #define N 9void parttion(int a,int m, int *p) int point,low,t; point=am; low=m;while(1) while(a+lowpoint); if(low*p) break; else t=alow; alow=a*p; a*p=t; am=a*p; a*p=point; for(int i=0;i9;i+) printf(%d ,ai); printf(nn);void quicksort(int a,int p
7、,int q) int j; j=q+1; if(pq) parttion(a,p,&j); quicksort(a,p,j-1); quicksort(a,j+1,q); void main() int i; int aN; printf(输入数组中待排序的数:n); for(i=0;iN;i+) scanf(%d,&ai); printf(n); quicksort(a,0,8); 五 、结果分析划分元素由 parttion( 1,10)来找到,a1=65是划分元素,经过第一次划分最终确定他是此数组中的第5个元素,parttiond的功能是将这个划分元素放到了它在排序好后的数组中所在的正确
8、位置,65前面的元素都比它小,65后面的元素都比它大。然后将这个集合分成两个部分,也按照这样的策越,,当数组元素是序(顺序或逆序)的时候,是快速排序的最坏情况,时间复杂度为O(),而平均情况时间是O(nlogn)。快速排序是不稳定的。一、题目:背包问题二 、算法介绍背包问题用到了贪心算法,贪心策略是按每一次装入的物品应使它占用的每一单位容量获得当前最大的单位效益。这就需使物品的装入次序按Pi/Wi比值的非增次序来考虑。在这种策略下的量度是已装入物品的累积效益值与所用容易之比。其量度标准是每次装入要使累计效益值与所用容量的比值有最多的增加或最少的减少。三 、程序流程图开始输入pN,wN并打印初始
9、化解向量xi=0(in)剩余容量cu=m对物品单位容量的效益值排序i=0 N结束icuXi=1cu=cu-wi xi=cu/m四 、源程序及实验结果#include #define N 7 /背包的个数void package(float p,float w,float m, float x,int n) int i,j; float t,cu; for(i=0;in;i+) for(j=i;jn;j+) if(pi*wjpj*wi) t=pi; pi=pj; pj=t; t=wi; wi=wj; wj=t; cu=m; for(i=0;icu) break; xi=1; cu=cu-wi;
10、if(in) xi=cu/wi;void main() int i; float m=15; float x7=0; float p7; float w7; printf(输入物品的效率值:n); for(i=0;iN;i+) scanf(%f,&pi); /各个背包单位容量的效益值 printf(输入物品的重量:n); for(i=0;iN;i+) scanf(%f,&wi); /各个背包单位容量的效益值 package(p,w,m,x,N); printf(输出解向量为:n); for(i=0;iN;i+) printf(x%d=%.5f ,i,xi); printf(n);五 、结果分析
11、对输入的物品按单位容量的效益值按非增次序排好序,如图所示,然后按照排好序后的物品来考虑,首先选择重量w为1,p为6,接着选择重量w为2,p为10,依次选择,最终当选择到w=3时,只剩下了2个容量,即选择该物品的2/3。通过与按容量非减和效益大小非增的两个为量度来比较,得到按照单位容量效益值非增的量度得到的是一个最优解。一、 题目:带有期限的作业排序二、 算法介绍目标函数为为量度。使用这一量度,下一个要计入的作业将是在满足所产生的J是一个可行解的限制条件下让得到最大增加的作业。这就要求按Pi的非增次序来考虑这些作业。三 、程序流程图开始输入pn,dnnd0=J0=0k=1,j1=1i=2退出结束
12、Nidi&dJr!=r NYdjrrr=r-1Yx=ki+Nx=r+1Y x-Jx+1=JxJr+1=ik+ 四 、源程序及实验结果#include void js(int d,int j,int n) int i,j1,k,r; d0=j0=0; k=1; j1=1; for(i=2;idi&djr!=r) r=r-1; if(djrr) for(j1=k;j1=r+1;j1-) jj1+1=jj1; jr+1=i; k+; void main() int i; int d6=0,2,2,1,3,3; int j6=0; js(d,j,5); for(i=1;iD2,即将该作业放到第三个任务
13、处,对于第5个作业,它的D为3,而前面已经被别的作业占用了,所以它放不了任务序列中。即作业的处理顺序为第1,2,4个作业依次处理。一、题目:单源点路径问题二 、算法介绍对于单源点最短路径问题,首先是逐条构造这些最短路径,可以使用迄今已生成的所有路径长度之和作为一种量度,为了使这一量度达到最小,其单独的每一条路径都必须具有最小长度。使用这一量度标准时,假定已经构造了i条最短路径,则下面要构造的路径应该是下一条最短的最小长度路径。生成从V0到所有其它结点的最短路径的贪心方法就是按照路径长度的非降次序生成这些路径。首先,生成一条到最近结点的最短路径;然后生成一条到第二近结点的最短路径。三 、程序流程
14、图开始单源点最短路径生成同图等价的邻接二维矩阵输入源点i=0NiN Y si=0,disti=COSTvii=i+1 S v=1,distv=0 i=0N打印结果iNYi+min=INFINITEu=v:j=0NjNj+YSu=1Sj=0&DISTjminNj=0YNjNmin=DISTju=jYj+Sj=0&DISTjminNYDISTj=min+COSTuj四 、源程序及实验结果#include int search(int t,int n,int m,int d) int k=tn; if(k=0) printf( %d ,dm); return(0); else printf(v%d
15、,search(t,k,m,d)+1); return(tn); void shortpaths(int v,int cost7,int dist,int n,bool s) int u,num,i,w; int front7=0,0,0,0,0,0,0; for(i=0;in;i+) si=0; disti=costvi; sv=1; distv=0; for(num=1;numn-1;num+) int min=10000; for(w=1;wn;w+) if(sw=0) if(distwmin) min=distw; u=w; su=1; for(w=1;wdistu+costuw) d
16、istw=distu+costuw; frontw=u; printf(路径值 源结点到各结点的最短路径n); for(i=0;i7;i+) printf(v%d ,search(front,i,i,dist)+1); printf(v%dn,i+1); void main() int i,j; int cost77= 0,20,50,30,200,200,200, 200,0,25,200,200,70,200, 200,200,0,40,25,50,200, 200,200,200,0,55,200,200, 200,200,200,200,0,10,70, 200,200,200,200
17、,200,0,50, 200,200,200,200,200,200,0 ; int front7=0,0,0,0,0,0,0; int dist7; bool s7; printf(有向图的成本邻接矩阵n); for(i=0;i7;i+) for(j=0;j7;j+) printf( %d ,costij); printf(n); shortpaths(0,cost,dist,7,s); 五 、结果分析由结果可知当从源点0出发去往其它结点均为最短路径,路径的长度即为此路径所经过的边的长度之和。首先最初产生从0点到它自身的路径,这条路径没有边,其长度为0,.在贪心算法的每一步中,产生下一个最短
18、路径。考虑加入一条最短的边,再从所有这些边中先选择最短的。可以验证按长度顺序产生最短路径时,下一条最短路径总是由一条已产生的最短路径加上一条边形成。实际上,下一条最短路径总是由已产生的最短路径再扩充一条最短的边得到的,且这条路径所到达的顶点其最短路径还未产生。例如第二条路径是第一条路径扩充一条边形成的;第三条路径则是第二条路径扩充一条边;第四条路径是第一条路径扩充一条边;第五条路径是第三条路径扩充一条边。如此即得到最终结果。该算法的时间复杂度为哦(n*n).一 、题目:每对结点之间的最短路径二 、算法介绍 本次用到了动态规划,动态规划的要点是从决策序列中选取最优决策序列。利用最优性原理,无论过
19、程的初始状态是什么,其余的决策都必须相对于初始决策所产生的状态构成一个最优决策序列。对于结点之间的最短路径问题,首先需要决策哪一个结点是该路径上具有最大编号的中间结点k,然后再去求取有i到k和由k到j这两对结点间的最短路径。当然,这两条路径都不可能有比k-1还大的中间结点。三 、程序流程图开始给定等价邻接矩阵将矩阵复制到二维数组中 k=1 k=k+1 i=1i=i+1 j=1j=j+1A(i,j)=MIN(A(i,j),A(i,k)+A(k,j)NYjn YinNYknN结束四 、源程序及实验结果#include #define MAX 1000#define N 3 void main()
20、int cost33= 0,4,11,6,0,2,3,MAX,0 ; int A33; int i,j,k; printf(成本矩阵如下:n); for(i=0;i3;i+) for(j=0;j3;j+) Aij=costij; for(k=0;kN;k+) for(i=0;iN;i+) for(j=0;jAik+Akj) Aij=Aik+Akj; for(i=0;iN;i+) for(j=0;jN;j+) printf(%d ,Aij); printf(n); printf(n); 五 、结果分析每对结点之间的最短路径问题是求满足下述条件的矩阵A,要求A中的任何元素A(i,j)是代表结点i到
21、结点j的最短路径的长度。考察G中一条由i到j的最路径,ij。这条路径由i出发,通过一些中间结点,在j处结束。如果k是这条最短路径上的一个中间结点,那么由i到k和由k到j的这两条子路径应分别是由i到k和由k到j的最短路径。否则,这条由i到j的路径就不是具有最小长度的路径。于是,最优性原理成立。如果k是编号最高的中间结点,那么由i到k的这条最短路径上就不会有比编号k-1更大的结点通过。同样,在k到j的那条最短路径上也不会有比编号k-1更大的结点通过。因此,可以把求取一条由i到j的最短路径看成是如下的过程:首先需要决策哪一个结点是该路径上具有最大编号的中间结点k,然后就再去求取由i到k和由k到j这两
22、对结点之间的最短路径。当然,这两条路径上都不可能有比k-1还大的中间结点。总结心得体会: 本次算法分析过程是层层推进的过程,首先是分治策越,然后是贪心算法,在就是动态规划。分治策越完成两个实验,一个是归并排序,然后是快速排序,归并是先划分然后反向归并。它是个稳定的排序算法。快速排序是先找到划分元素的位置把它放在正确的位置上,然后按这个元素划分成两部分,它是不稳定的算法,但都是一种递归算法策越。贪心算法是完成的背包问题和带有限期限值的作业排序算法,贪心算法主要是贪心策越的选取,只有正确的选择最优策越才能求出最优解。动态规划是个多阶段的决策过程,通过决策可以使得解的范围缩小。算法上机实验,主要是用
23、实践来证明理论的正确性。算法设计的学习是很难的,上机也不是那么的容易。好的算法,能够很好地解决一类问题。同样的问题有不同的算法来解决。像排序算法,有选择,冒泡,归并,快速等等。好的方法不仅在时间复杂度上和空间复杂度上都能保持在较小的值,节省了资源。一个算法题目的求解首先要分析,然后选择合理的算法,然后上机验证正确与否,也是个相当严谨的过程。我开始只是抱着一种验证性的思想来完成实验,但是经过老师的点评,发现要学好算法,即必须严谨,数据要键盘输入,要符合大众的,不能抱着马马虎虎的思想来完成。每一次的归并,每一次划分元素的查找都必须输出,这样才能使得结果有说服力,让人理解。算法的时间复杂度要经过详尽的分析,只有深入的了解才能够明白她们的优劣所在。总之,算法的学习确实对个人的编程能力有很多的帮助,它让人又一定方法去针对相应的问题。要想学好算法必须思考,要上机,并且还要严谨。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1