1、1.抽象数据类型ADT List 数据对象 D ai | ai ElemSet, i=1,2,.,n, n0 数据关系 R1 |ai-1 ,aiD, i=2,.,n 基本操作 virtual void clear() = 0; bool insert(const Elem&) = 0; bool append(const Elem& lbool remove(Elem&void setStart() = 0; void setEnd() = 0; void prev() = 0; void next() = 0; int leftLength() const = 0; int rightLen
2、gth() const = 0; bool setPos(int pos) = 0; bool getValue(Elem&) const = 0; void print() const = 0;2.程序的流程(1) 输入模块:输入要排序的数的数量n(2) 处理模块:系统产生n个随机数,对随机数进行排序(3) 输出模块:将排序的结果输出3.算法的基本思想1、 随机数的产生:利用srand()产生随机数。2、 快速排序:选定一记录R,将所有其他记录关键字k与记录R的关键字k比较, 若 kk 则将记录换至R之后,继续对R前后两部分记录进行快速排序,直至排序范围为13、 插入排序:逐个处理待排序的记
3、录,每个新记录与前面已排序的子序列进行比较,将它插入到子序列中正确的位置4、 冒泡排序:比较并交换相邻的元素对,直到所有元素都被放到正确的地方为止。5、 归并排序:将两个或者多个有序表归并成一个有序表6、 堆排序:首先将数组转化为一个满足堆定义的序列,然后将堆顶的最大元素取出,再将剩下的数排成堆,再取堆顶数值,。如此下去,直到堆为空。到最后结束时,就排出了一个由小到大排列的数组。三、详细设计(1)产生随机数:直接调用函数srand(),以时间作为随机种子进行选择,并把随机数装入数组中unsigned long int *Sort:setRan(unsigned long int num) un
4、signed long int *ra; ra=(unsigned long int*)malloc(num*sizeof(unsigned long int); srand(time(NULL); for(unsigned long int m=0;mnum;m+) ram=rand(); coutendl; return ra;(2)快速排序:要实现快速排序首先选择一个轴值,这里选取数组第一个为轴值。定义两个标识low,high。high标识最后一个元素的位置,从后向前,将关键字与轴值比较,直至遇到小于轴值的关键字,前移,low标识在第二个元素的位置,从前向后,将关键字与轴值比较,直至遇到
5、大于轴值的关键字,后移。当low,high相遇后第一趟排序结束。调整数列,轴值左边的为比轴值小的,右边为比轴值大的。对轴值左边(即low到pivotkey-1的数)和右边的子列(pivotkey+1到high的数)分别进行上述递归快速排序,直到范围为1结束。int partition(int a,int low,int high)/快速排序中的一趟 int pivotkey; /作为枢轴来使用 pivotkey=alow; while(low=pivotkey) -high; alow=ahigh;alow +low; ahigh=alow; alow=pivotkey; return low
6、;void qsort(int a,int low,int high)/快速排序的递归形式 int pivotloc; if(lowsetNum(); LARGE_INTEGER Freg; LARGE_INTEGER Count1,Count2; QueryPerformanceFrequency(&Freg); QueryPerformanceCounter(&Count1);/获取时间Count1 double d; int temp,j; for (unsigned long int i=0;igetRanNum();i+) j=i; temp=si; while (j=1 & tem
7、pSortNum+; if(j1) this- sj=temp;Count2);/获取时间Count2 d=(double)(Count2.QuadPart-Count1.QuadPart)/(double)Freg.QuadPart*1000.0;/计算时间差,d的单位为ms.插入排序算法对RanNum个随机数排序时间为为d ms.个随机数交换次数为SortNum次。(4) 冒泡排序(bubble sort):将被排序的记录数组R1.n垂直排列,每个记录Ri看作是重量为Ri.key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上飘浮。如此反
8、复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者在上,则交换二者的位置。即依次比较(Rn,Rn-1),(Rn-1,Rn-2),(R2,R1);对于每对气泡(Rj+1,Rj),若Rj+1.keyRanNum);i+) for(int j=i+1;jsj) temp = si; si=sj; sj=temp; this- 冒泡排序算法对个随机数排序时间为 (5) 堆排序:堆排序与其他排序算法最大的区别是它依靠一种特殊的数据结构堆来进行排序。堆是一种完全二叉树,并且根节点不大于左右子树中的所有节点,ni=n2*i&ni=n2*
9、i+1。因此堆排序算法首先要将给出的无序数组构造成一个堆,然后输出根节点(最小元素),将剩余元素重新恢复成堆,再次输出根节点。依次类推,直至最后一个节点输出,此时堆排序完成。heapRestor(unsigned long int *s,int i,int m) int ma; if(imin(s2*i,s2*i+1) if(s2*iSortNum+2; else if(i=1;num-)heapRestor(s,num,m);heapSort(unsigned long int *s1,unsigned long int *s2) int i,num; num=this-RanNum;hea
10、pCreat(s1,this- for(i=0; s2i=s11; s11=s1num;heapRestor(s1,1,-num);堆排序算法对 (6) 合并排序:这里的合并排序和下边要描述的快速排序都采用了分而治之的思想,但两者仍然有很大差异。合并排序是将一个无序数组n1r分成两个数组n1r/2与nr/2+1r,分别对这两个小数组进行合并排序,然后再将这两个数组合并成一个大数组。由此我们看出合并排序时一个递归过程(非递归合并排序这里不做讨论)。合并排序的主要工作便是“合并”,两个小规模数组合并成大的,两个大的再合并成更大的,当然元素比较式在合并的过程中进行的。mergeSort(unsign
11、ed long int *s,int left,int right) int i; if(left right) i=(left + right)/2; mergeSort(s,left, i); mergeSort(s, i + 1, right); Merge(s, left, i, right);int Sort:partition(unsigned long int *s,int low,int high) int key,i,p,r; p=low; r=high; key=sp; while(pp;i-) if(si清空。释放数组,将数组大小和栅栏置0.void clear() de
12、lete listArray;2将栅栏赋初值0,放在开头。void setStart() fence = 0;3将栅栏指向数组最后。void setEnd() fence = listSize;4获得当前的位置。用栅栏的指向即可直接获得。void prev() if (fence != 0) fence-;5获得最大值的大小,由栅栏可直接获得。void next() if (fence 返回当前位置左边的长度。直接返回栅栏的值获得。int leftLength() const return fence;7返回当前位置右边的长度。用最大长度减去当前栅栏的值。int rightLength() c
13、onst return listSize - fence;8设置当前位置,将值直接赋予栅栏。bool setPos(int pos) if (pos = 0) & (pos = listSize);9返回当前的值。bool getValue(Elem& it) const if (rightLength() = 0) return false; else it = listArrayfence; return true;(4)算法的时空分析插入排序:直接插入排序算法必须进行n-1趟。最好情况下,即初始序列有序,执行n-1趟,但每一趟只比较一次,移动元素两次,总的比较次数是(n-1),移动元素次
14、数是2(n-1)。因此最好情况下的时间复杂度就是O(n)。最坏情况(非递增)下,最多比较i次,因此需要的比较次数是:所以,时间复杂度为O(n2)。冒泡排序:当原始数据正向有序时,冒泡排序出现最好情况。此时,只需进行一趟排序,作n-1次关键字比较,因此最好情况下的时间复杂度是O(n)。当原始数据反向有序时,冒泡排序出现最坏情况。此时,需进行n-1趟排序,第i趟作(n-i)次关键字间的比较,并且需执行(n-i)次元素交换,所以,比较次数为:因此,最坏情况下的时间复杂度为O(n2)快速排序:如果每一次分划操作后,左、右两个子序列的长度基本相等,则快速排序的效率最高,其最好情况时间复杂度为O(nlog
15、2n);反之,如果每次分划操作所产生的两个子序列,其中之一为空序列,此时,快速排序效率最低,其最坏情况时间复杂度为O(n2)。如果选择左边第一个元素为主元,则快速排序的最坏情况发生在原始序列正向有序或反向有序时。快速排序的平均情况时间复杂度为O(nlog2n)。堆排序:堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。堆排序的最坏时间复杂度为O(nlogn)。堆排序的平均性能较接近于最坏性能。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是不稳定的,算法时间复杂度O(nlogn)。归并排序:在最佳、平均、最差情况
16、下,时间复杂度为(n log n),不足的就是需要两倍的空间代价,当输入的待排序数据存储在链表中时,归并排序是一个很好的选择.(5)函数的调用关系图用户输入排序的元素个数n产生n个随机数主程序对随机数进行排序输出(6)输入和输出的格式输入 请输入排序规模:/提示输入 等待输入 输出 插入排序算法对n个随机数排序时间为 插入排序算法对n个随机数交换次数为 冒泡排序算法对n个随机数排序时间为 冒泡排序算法对n个随机数交换次数为 堆排序算法对n个随机数排序时间为 堆排序算法对n个随机数交换次数为 合并排序算法对n个随机数排序时间为 合并排序算法对n个随机数交换次数为快速排序算法对n个随机数排序时间为
17、 快速排序算法对n个随机数交换次数为 排序后,前50个有序元素为:四、用户使用说明(可选)1、本程序的运行环境为DOS操作系统,执行文件为conversion.exe2、运行程序时五:实现图1 控制台程序实验结果:实验分别实现插入排序、冒泡排序、堆排序、合并排序、快速排序,以不同规模(100,1000,2000,5000,10000,100000个数据)的随机数作为测试数据集,实验结果截图如下:排序规模为100排序规模为:10002000500010000100000(六)算法性能分析在程序中我们根据数据规模的不同产生不同的随机整型数组,然后分别让不同的排序算法来进行从小到大的排序。这里需要注意的是:每种排序算法在相同的输入规模中原始无序数据都是一样的。例如五种排序算法要对长度为100的无序数组进行排序,它们所要排序的无序数组都是一样的,我们以此来保证实验的公正性。在这里我们认为比较次数是排序算法的主要
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1