数据结构课程设计_第1页
数据结构课程设计_第2页
数据结构课程设计_第3页
数据结构课程设计_第4页
数据结构课程设计_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、数据结构课程设计题 目利用随机函数产生30000个随机整数,利用插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归弁排序 等排序方法进行排序,统计每一种排序上机所花费的时间,弁和理论上时间进行对比分析。学生姓名学号学院专业指导教师年 月 日设计题目利用随机函数产生30000个随机整数,利用插入排序、起泡排序、快 速排序、选择排序、堆排序、归并排序等排序方法进行排序,统计每 一种排序上机所花费的时间,并和理论上时间进行对比分析。二、 算法设计的思想1简单选择排序操作方法:第一趟, 从 n 个记录中找出关键码最小的记录与第一个记录交换;第二趟, 从第二个记录开始的n-1 个记录中再选出关

2、键码最小的记录与第二个记录交换;如此,第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,直到整个序列按关键码有序。【效率分析】空间效率:仅用了一个辅助单元。时间效率:简单选择排序中,所需进行记录移动的操作次数较小,其最小值为0,最大值为3( n-1) 。然而,无论记录的初始排列如何,所需进行的关键字之间的比较次数相同,均为n(n-1)/2。因此,总的时间复杂度也是 O(n2)。2直接插入排序设有 n 个记录,存放在数组r 中,重新安排记录在数组中的存放顺序,使得按关键码有序。即 r1.key < r2.key << rn.key先来看

3、看向有序表中插入一个记录的方法:设1 < j & n , r1.key <r2.key << rj-1.key ,将 rj插入,重新安排存放顺序,使得r1.key< r2.key << rj.key ,得到新的有序表,记录数增1。【效率分析】空间效率:仅用了一个辅助单元。时间效率:向有序表中逐个插入记录的操作,进行了n-1 趟,每趟操作分为比较关键码和移动记录,而比较的次数和移动记录的次数取决于待排序列按关键码的初始排列。最好情况下:即待排序列已按关键码有序,每趟操作只需1 次比较 2 次移动。总比较次数=n-1 次总移动次数=2(n-1)次最

4、坏情况下:即第j 趟操作,插入记录需要同前面的j 个记录进行j 次关键码比较,移动记录的次数为j+2 次。平均情况下:即第j 趟操作,插入记录大约同前面的j/2 个记录进行关键码比较,移动记录的次数为j/2+2 次。由此,直接插入排序的时间复杂度为O(n2)。是一个稳定的排序方法3希尔排序(Shell s Sort)直接插入排序算法简单,在n 值较小时,效率比较高,在n 值很大时,若序列按关键码基本有序,效率依然较高,其时间效率可提高到O(n)。希尔排序即是从这两点出发,给出插入排序的改进方法。希尔排序方法:1 .选择一个步长序列t1, t2,tk,其中ti>tj, tk=1;2 .按步

5、长序列个数k,对序列进行k趟排序;3 .每趟排序,根据对应的步长ti,将待排序列分割成若干长度为m的子序列,分别对各子表进行直接插入排序。仅步长因子为1 时, 整个序列作为一个表来处理,表长度即为整个序列的长度。希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于步长因子序列的选取, 特定情况下可以准确估算出关键码的比较次数和记录的移动次数。目前还没有人给出选取最好的步长因子序列的方法。步长因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:步长因子中除 1外没有公因子,且最 后一个步长因子必须为1。希尔排序方法是一个不稳定的排序方法。4 .冒泡排序冒泡排序方法:对n个记录的表

6、,第一趟冒泡得到一个关键码最大的记录 rn, 第二趟冒泡对n-1个记录的表,再得到一个关键码最大的记录rn-1,如此重复, 直到n个记录按关键码有序的表。【效率分析】空间效率:仅用了一个辅助单元。时间效率:总共要进行n-1趟冒泡,对j个记录的表进行一趟冒泡需要j-1次关 键他比较。移动次数:最好情况下:待排序列已有序,不需移动。5 .快速排序快速排序是通过比较关键码、交换记录,以某个记录为界(该记录称为支点),将待排序列分成两部分。其中,一部分所有记录的关键码大于等于支点记录的关键 码,另一部分所有记录的关键码小于支点记录的关键码。我们将待排序列按关键 码以支点记录分成两部分的过程,称为一次划

7、分。对各部分不断划分,直到整个 序列按关键码有序。【效率分析】空间效率:快速排序是递归的,每层递归调用时的指针和参数均要用栈来存放,递归调用层次数与上述二叉树的深度一致。因而,存储开销在理想情况下为O(log2n),即树的高度;在最坏情况下,即二叉树是一个单链,为 O(n)。时间效率:在n个记录的待排序列中,一次划分需要约n次关键码比较,时效为 O(n),若设T(n)为对n个记录的待排序列进行快速排序所需时间。理想情况下:每次划分,正好将分成两个等长的子序列,则T(n) < cn+2T(n/2) c 是一个常数< cn+2(cn/2+2T(n/4)=2cn+4T(n/4)&

8、 2cn+4(cn/4+T(n/8)=3cn+8T(n/8)< cnlog2n+nT(1)=O(nlog2n)最坏情况下:即每次划分,只得到一个子序列,时效为 O(n2)。快速排序是通常被认为在同数量级(O(nlog2n)的排序方法中平均性能最好的。但若初始序列按关键码有序或基本有序时,快排序反而蜕化为冒泡排序。为改进之,通常以“三者取中法”来选取支点记录,即将排序区间的两个端点与中点三 个记录关键码居中的调整为支点记录。快速排序是一个不稳定的排序方法。6 .堆排序堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。堆排序的最坏时间复杂

9、度为O(nlogn) o堆序的平均性能较接近于最坏性能。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1),它是不稳定的排序方法。7 .归弁排序归并操作的工作原理如下:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列,设定两个指针,最初位置分别为两个已经排序序列的起始位置。比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 。重复步骤3直到某一指针达到序列尾,将另一序列剩下的所有元素直接复制到合并序列尾。速度仅次于快速排序,但较稳定。归并排序的时间复杂度为 O(nlogn)。三、算法设计分析程

10、序总体采用分块化设计,每种排序的函数都以其相应的名字保存,在主程序调用时用#include “*cpp ”调用。这样的总体布局将各个功 能隔离开来,每个模块负责每个模块的功能,使得程序的布局简单明了 < 且子程序只有在被调用时才会运行大大节约系统资源减少了运算时间。同时由于功能的隔离使得程序的扩展性大大提高,无论程序将要任何改 动时,都会方便很多。四、源代码以“20106498.cpp”保存,其他子函数分别保存,以下是主函数的代码。#include<iostream>#include<conio.h>#include<time.h>#include”快

11、速排序.cpp"#include"堆排序.cpp"#include"直接插入排序.cpp"#include"选择排序.cpp"#include"冒泡排序.cpp"#include"希尔排序.cpp"#include"归并排序.cpp"using namespace std;int main()clock_t startfinish;int i,time1,time2,time3,time4,time5,time6,time7;int a30000,b30000;sr

12、and(time(0);for(i=0;i<30000;i+)ai=rand();cout<<"*n"cout<<"t 选择排序n"cout<<"*n"for(i=0;i<30000;i+)bi=ai;start=clock();choices_sort(b);finish=clock();time1=finish-start;printf(" 选择排序耗时%d 毫秒 !nnn",time1);cout<<"I*n"cout<&l

13、t;"t 直接插入排序n"cout<<"I*n"for(i=0;i<30000;i+)bi=ai;start=clock();direct(b);finish=clock();time2=finish-start;printf(" 直接插入排序耗时%d 毫秒 !nnn",time2);cout<<"I*n"cout<<"t 堆排序 n"cout<<"*n"for(i=0;i<30000;i+)bi=ai;start=

14、clock();heap_sort(b,30000);finish=clock();time3=finish-start;printf(" 堆排序耗时%d 毫秒 !nnn",time3);cout<<"*n"cout<<"t 快速排序n"cout<<"I*n"for(i=0;i<30000;i+)bi=ai;start=clock();sort(b,0,29999);finish=clock();time4=finish-start;printf(" 快速排序耗时

15、%d 毫秒 !nnn",time4);cout<<"I*n"cout<<"t 冒泡排序n"cout<<"I*n"for(i=0;i<30000;i+)bi=ai;start=clock();bubble_sort(b);finish=clock();time5=finish-start;printf(" 冒泡排序耗时%d 毫秒 !nnn",time5);cout<<"*n"cout<<"t 希尔排序n"

16、;cout<<"*n"for(i=0;i<30000;i+)bi=ai;start=clock();shellsort(b,30000);finish=clock();time6=finish-start;printf(" 希尔排序耗时%d 毫秒 !nnn",time6);cout<<"*n"cout<<"t 归并排序n"cout<<"*n"for(i=0;i<30000;i+)bi=ai;start=clock();MergeSort

17、(b,0,29999);finish=clock();time7=finish-start;printf(" 归并排序耗时%d 毫秒 !nnn",time7);getch();return 0;.cpp保存以下是直接插入排序的函数,以“直接插入排序#include<iostream>#include<conio.h>using namespace std;void direct(int a)int i,j,w;for(i=0;i<30000;i+)for(j=i;j>=0;j-)if(aj>=aj+1)w=aj;aj=aj+1;aj

18、+1=w;以下是选择排序的函数,以“选择排序 .cpp”保存#include <iostream>#include <conio.h>using namespace std;void choices_sort(int a)int i,j,k,t;for(i=0;i<30000;i+)k=i;for(j=i+1;j<30000;j+)if(ak>aj)k=j;t=ai;ai=ak;ak=t;以下是冒泡排序的函数,以“冒泡排序 .cpp”保存#include <iostream>#include <conio.h>using nam

19、espace std;void bubble_sort(int a)int i,j,w;for(i=0;i<30000;i+)for(j=0;j<30000-i;j+)if(aj>aj+1)w=aj;aj=aj+1;aj+1=w;以下是希尔排序的函数,以“希尔排序 .cpp”保存#include<iostream>#include<conio.h>#include<time.h>using namespace std;void shellsort(int a,int n)int d,i,j,temp;for (d=n/2;d>=1;d

20、=d/2)for(i=d;i<n;i+)temp=ai;for(j=i-d;(j>=0)&&(aj>temp);j=j-d)aj+d=aj;aj+d=temp;以下是快速排序的函数,以“快速排序 .cpp”保存#include<iostream>#include<conio.h>using namespace std;void sort(int a,int x,int y)int xx=x,yy=y;int k=ax;if (x>=y)return;while(xx!=yy)while(xx<yy&&ayy&

21、gt;=k)yy-;axx=ayy;while(xx<yy&&axx<=k)xx+;ayy=axx;axx=k;sort(a,x,xx-1);sort(a,xx+1,y);以下是堆排序的函数,以“堆排序.cpp”保存#include<iostream>#include<conio.h>#include<time.h>using namespace std;void sift(int *x, int n, int s)int t, k, j;t = *(x+s);k = s;j = 2*k + 1;while (j<n)if

22、(j<n-1 && *(x+j) < *(x+j+1)就继续下一轮比较,否则调整。*/j+;if (t<*(x+j)*(x+k) = *(x+j);k = j;调整 */j = 2*k + 1;else个堆了,退出循环。*/break;*(x+k) = t;置 */void heap_sort(int *x, int n)int i, k, t;for (i=n/2-1; i>=0; i-)sift(x,n,i);for (k=n-1; k>=1; k-)/* 暂存开始元素*/* 开始元素下标*/* 右子树元素下标*/*判断是否满足堆的条件:满足/

23、*调整 */* 调整后,开始元素也随之/*没有需要调整了,已经是/* 开始元素放到它正确位/*初始建堆 */* 堆顶放到最后*/t = *(x+0);*(x+0) = *(x+k);*(x+k) = t;/* 剩下的数再建堆*/sift(x,k,0);以下是归并排序的函数,以“归并排序 .cpp”保存#include <iostream>#include <conio.h>using namespace std;void Merge(int *R,int low,int m,int high)int i=low,j=m+1,p=0;int *R1;R1=(int *)malloc(high-low+1)*sizeof(int);if(!R1)return;while(i<=m&&j<=high)R1p+=(Ri<=Rj)?Ri+:Rj+;while(i<=m)R1p+=Ri+;while(j<=high)R1p+=Rj+;for(p=0,i=low;i<=high;p+,i+)Ri=R1p;v

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论