当前位置:文档之家› 数据结构课程设计报告

数据结构课程设计报告

数据结构课程设计报告题目:5班级:计算机1102学号:**********姓名:***指导老师:***一:需求分析1.运行环境TC2.程序所需实现的功能几种排序算法的演示,要求给出从初始开始时的每一趟的变化情况,并对各种排序算法性能作分析和比较:(1)直接插入排序;(2)折半插入排序;(3)冒泡排序;(4)简单选择排序;(5)快速排序;(6)堆排序;(7)归并排序.二:设计说明1.算法设计的思想1)、直接插入排序排序过程:整个排序过程为n-1趟插入,即先将序列中第1个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序。

2)、折半插入排序排序过程:用折半查找方法确定插入位置的排序叫折半插入排序。

3)、冒泡排序排序过程:将第一个记录的关键字与第二个记录的关键字进行比较,若为逆序r[1].key>r[2].key,则交换;然后比较第二个记录与第三个记录;依次类推,直至第n-1个记录和第n个记录比较为止——第一趟冒泡排序,结果关键字最大的记录被安置在最后一个记录上。

对前n-1个记录进行第二趟冒泡排序,结果使关键字次大的记录被安置在第n-1个记录位置。

重复上述过程,直到“在一趟排序过程中没有进行过交换记录的操作”为止4)、简单选择排序排序过程:首先通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将它与第一个记录交换。

再通过n-2次比较,从剩余的n-1个记录中找出关键字次小的记录,将它与第二个记录交换。

重复上述操作,共进行n-1趟排序后,排序结束。

5)、快速排序基本思想:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序。

排序过程:对r[s……t]中记录进行一趟快速排序,附设两个指针i和j,设枢轴记录rp=r[s],x=rp.key。

初始时令i=s,j=t。

首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp交换。

再从i所指位置起向后搜索,找到第一个关键字大于x的记录,和rp交换。

重复上述两步,直至i==j为止。

再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止。

6)、堆排序排序过程:将无序序列建成一个堆,得到关键字最小(或最大)的记录;输出堆顶的最小(大)值后,使剩余的n-1个元素重又建成一个堆,则可得到n个元素的次小值;重复执行,得到一个有序序列,这个过程叫堆排序。

7)、归并排序归并——将两个或两个以上的有序表组合成一个新的有序表,叫归并。

2-路归并排序排序过程:设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1。

两两合并,得到⎣n/2⎦个长度为2或1的有序子序列。

再两两合并,……如此重复,直至得到一个长度为n的有序序列为止。

2、程序的主要流程图3⑴直接插入排序;typedef struct{ int key;float info;}JD;void straisort(JD r[],int n) //直接插入排序{ int i,j;for(i=2;i<=n;i++){ r[0]=r[i]; //复制为哨兵j=i-1;while(r[0].key<r[j].key){ r[j+1]=r[j]; //记录后移j--;}r[j+1]=r[0]; //插入到正确位置}}⑵折半插入排序;void binsort(JD r[],int n) //折半插入排序{ int i,j,x,s,m,k;for(i=2;i<=n;i++){ r[0]=r[i]; //将r[i]暂存到r[0]x=r[i].key;s=1; j=i-1;while(s<=j) //在r[s..j]中折半查找有序插入的位置{ m=(s+j)/2; //折半if(x<r[m].key) j=m-1; //插入点在低半区else s=m+1; //插入点在高半区}for(k=i-1;k>=s;k--)r[k+1]=r[k]; //记录后移r[s]=r[0]; //插入}}⑶冒泡排序;void bubble_sort(JD r[],int n) //冒泡排序{ int m,i,j,flag=1;JD x;m=n-1;while((m>0)&&(flag==1)){ flag=0;for(j=1;j<=m;j++)if(r[j].key>r[j+1].key){ flag=1;x=r[j];r[j]=r[j+1];r[j+1]=x;}m--;}}⑷简单选择排序;void smp_selesort(JD r[],int n) //简单选择排序{ int i,j,k;JD x;for(i=1;i<n;i++){ k=i;for(j=i+1;j<=n;j++)if(r[j].key<r[k].key) k=j; //在r[i..n]中选择j最小的记录if(i!=k){ x=r[i]; //与第i个记录交换r[i]=r[k];r[k]=x;}}}⑸快速排序;void qksort(JD r[],int t,int w) //快速排序{ int i,j,k;JD x;if(t>=w) return;i=t; j=w; x=r[i]; //用字表的第一个记录作枢轴记录while(i<j) //从表的两端交替地想中间扫描{ while((i<j)&&(r[j].key>=x.key)) j--;if(i<j) { r[i]=r[j]; i++; } //将比枢轴记录小的记录交换到低端while((i<j)&&(r[i].key<=x.key)) i++;if(i<j) { r[j]=r[i]; j--; } //将比枢轴记录大的记录交换到高端}r[i]=x; //枢轴记录到位qksort(r,t,j-1);qksort(r,j+1,w); //返回枢轴所在位置}⑹堆排序;int sift(JD r[],int k,int m) //堆排序{ int i,j;JD x;i=k; x=r[i]; j=2*i;while(j<=m) //沿key较大的孩子结点向下筛选{ if((j<m)&&{r[j].key>r[j+1].key)) j++; //j为key较大的记录的下标if(x.key>r[j].key) //rc应插入在位置i上{ r[i]=r[j];i=j;j*=2;}else j=m+1;}r[i]=x; //插入}⑺归并排序。

void mergesort(JD r[],int n) //归并排序{ int i,s=1;JD t[M];while(s<n){ tgb(s,n,r,t);s*=2;if(s<n) { tgb(s,n,t,r); s*=2; }else { i=1;while(i<=n) r[i]=t[i++];}}}void tgb(int s,int n,JD r[],JD t[]){ int i=1;while(i<=(n-2*s+1)){ merge(r,i,i+s-1,i+2*s-1,t);i=i+2*s;}if(i<(n-s+1)) merge(r,i,i+s-1,n,t);elsewhile(i<=n) t[i]=r[i++];}void merge(JD r[],int h,int m,int w,JD t[]){ int i,j,k;i=h; j=m+1; k=h-1;while((i<=m)&&(j<=w)){ k++;if(r[i].key<=r[j].key)t[k]=r[i++];elset[k]=r[j++];}if(i>m)while(j<=w) t[++k]=r[j++];elsewhile(i<=m) t[++k]=r[i++];}三:上机结果及体会1.实际完成的情况说明(完成的功能,支持的数据类型等)类型int,输入10个数据,能够以直接插入排序,折半插入排序,冒泡排序,简单选择排序,快速排序,堆排序,归并排序。

2.程序的性能分析,包括时空分析A.直接插入排序在整个排序过程(进行n-1趟插入排序)中,若待排序记录按关键字从小到大排列(正序),所需进行关键字间比较的次数达最小值n-1,数据移动次数为2(n-1);若待排序记录按关键字从大到小排列(逆序),关键字间的比较次数达最大值(n+2)(n-1)/2,记录的移动次数也达最大值(n+4)(n-1)/2;若待排序记录是随机的,即待排序列中的记录可能出现的各种排列的概率相同,则我们可取上述最小值和最大值的平均值,作为直接插入时所需进行关键字间的比较次数和移动记录的次数,约为n2/4。

由此,直接插入排序的时间复杂度为O(n2)、空间复杂度为S(n)=O(1)。

所以直接插入排序算法简便,且容易实现。

当待排序记录的数量n很小时,只是一种很好的排序方法。

但是,通常待排序序列中的记录数量n很大,则不宜采用直接插入排序。

B.折半插入排序它所需要的关键字比较次数与关键字排列次序无关,仅依赖于数据元素个数。

在插入第i个数据元素时,需要经过「log2i「+1次关键字比较,才能确定它的插入位置。

因此将n个数据元素(为推导方便,设为n=2k)用折半插入排序所进行的关键字比较次数为:n*log2n。

当n较大时,总的关键字比较次数比直接插入排序的最坏情况要少得多,但比其最好情况要多。

折半插入排序所需要附加存储空间和直接插入排序相同,从时间上比较,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变。

因此,折半插入排序的时间复杂度仍为O(n2),空间复杂度为S(n)=O(1)。

折半插入排序是一种稳定的排序。

C.冒泡排序分析冒泡排序的效率,若初始序列为“正序”序列,则只需要进行一趟排序,在排序过程中进行n-1次关键字间的比较,且不移动记录;反之,若初始序列为“逆序”序列,则需要进行n-1趟排序,需要进行n(n-1)/2次比较,且移动的次数为3n(n-1)/2。

因此,总的时间复杂度为O(n2)、空间复杂度为S(n)=O(1)。

冒泡排序需要一个附加存储空间以实现数据元素的交换。

冒泡排序是一种稳定的排序方法。

D.简单选择排序简单选择排序过程中,所需进行记录移动的操作次数较少,其最小值为“0”,最大值为3(n-1)。

然而,无论记录的初始排序如何,所需进行的关键字间的比较次数相同,均为n(n-1)/2。

相关主题