几种排序算法的平均性能比较(实验报告)
各种排序对比实验报告

一、实验目的通过对不同排序算法的实验对比,分析各种排序算法的效率、稳定性和适用场景,为实际应用中选择合适的排序算法提供参考。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 测试数据:随机生成长度为10000的整数数组三、实验方法1. 实验数据:随机生成长度为10000的整数数组,作为排序算法的输入数据。
2. 实验算法:选择以下排序算法进行对比实验:- 冒泡排序(Bubble Sort)- 选择排序(Selection Sort)- 插入排序(Insertion Sort)- 快速排序(Quick Sort)- 归并排序(Merge Sort)- 堆排序(Heap Sort)3. 实验步骤:(1)对每种排序算法进行编写和实现;(2)将测试数据分别输入到每种排序算法中,记录排序过程的时间;(3)比较不同排序算法的排序时间,分析其效率;(4)观察排序过程中数据的变化,分析其稳定性;(5)总结各种排序算法的适用场景。
四、实验结果与分析1. 冒泡排序(Bubble Sort)- 效率:时间复杂度为O(n^2),空间复杂度为O(1);- 稳定性:稳定排序算法;- 适用场景:数据量较小、基本有序的数据。
2. 选择排序(Selection Sort)- 效率:时间复杂度为O(n^2),空间复杂度为O(1);- 稳定性:不稳定排序算法;- 适用场景:数据量较小、基本有序的数据。
3. 插入排序(Insertion Sort)- 效率:时间复杂度为O(n^2),空间复杂度为O(1);- 稳定性:稳定排序算法;- 适用场景:数据量较小、基本有序的数据。
4. 快速排序(Quick Sort)- 效率:平均时间复杂度为O(nlogn),最坏情况时间复杂度为O(n^2),空间复杂度为O(logn);- 稳定性:不稳定排序算法;- 适用场景:数据量较大、基本有序或无序的数据。
5. 归并排序(Merge Sort)- 效率:时间复杂度为O(nlogn),空间复杂度为O(n);- 稳定性:稳定排序算法;- 适用场景:数据量较大、基本有序或无序的数据。
算法实验报告结果分析

一、实验背景随着计算机科学技术的不断发展,算法作为计算机科学的核心内容之一,其重要性日益凸显。
为了验证和评估不同算法的性能,我们进行了一系列算法实验,通过对比分析实验结果,以期为后续算法研究和优化提供参考。
二、实验方法本次实验选取了三种常见的算法:快速排序、归并排序和插入排序,分别对随机生成的数据集进行排序操作。
实验数据集的大小分为10000、20000、30000、40000和50000五个级别,以验证算法在不同数据量下的性能表现。
实验过程中,我们使用Python编程语言实现三种算法,并记录每种算法的运行时间。
同时,为了确保实验结果的准确性,我们对每种算法进行了多次运行,并取平均值作为最终结果。
三、实验结果1. 快速排序快速排序是一种高效的排序算法,其平均时间复杂度为O(nlogn)。
从实验结果来看,快速排序在所有数据量级别下均表现出较好的性能。
在数据量较小的10000和20000级别,快速排序的运行时间分别为0.05秒和0.1秒;而在数据量较大的40000和50000级别,运行时间分别为0.8秒和1.2秒。
总体来看,快速排序在各个数据量级别下的运行时间均保持在较低水平。
2. 归并排序归并排序是一种稳定的排序算法,其时间复杂度也为O(nlogn)。
实验结果显示,归并排序在数据量较小的10000和20000级别下的运行时间分别为0.15秒和0.25秒,而在数据量较大的40000和50000级别,运行时间分别为1.5秒和2.5秒。
与快速排序相比,归并排序在数据量较小的情况下性能稍逊一筹,但在数据量较大时,其运行时间仍然保持在较低水平。
3. 插入排序插入排序是一种简单易实现的排序算法,但其时间复杂度为O(n^2)。
实验结果显示,插入排序在数据量较小的10000和20000级别下的运行时间分别为0.3秒和0.6秒,而在数据量较大的40000和50000级别,运行时间分别为8秒和15秒。
可以看出,随着数据量的增加,插入排序的性能明显下降。
5种排序算法性能比较总结

5种排序算法性能比较总结1、概述本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序、插入排序、归并排序、希尔排序、快速排序等。
算法性能比较如下图所示:2、选择排序选择排序的第一趟处理是从数据序列所有n个数据中选择一个最小的数据作为有序序列中的第1个元素并将它定位在第一号存储位置,第二趟处理从数据序列的n-1个数据中选择一个第二小的元素作为有序序列中的第2个元素并将它定位在第二号存储位置,依此类推,当第n-1趟处理从数据序列的剩下的2个元素中选择一个较小的元素作为有序序列中的最后第2个元素并将它定位在倒数第二号存储位置,至此,整个的排序处理过程就已完成。
代码如下:3、插入排序直接插入排序法的排序原则是:将一组无序的数字排列成一排,左端第一个数字为已经完成排序的数字,其他数字为未排序的数字。
然后从左到右依次将未排序的数字插入到已排序的数字中。
代码如下:4、归并排序算法描述:把序列分成元素尽可能相等的两半。
把两半元素分别进行排序。
把两个有序表合并成一个。
代码如下:5、希尔排序希尔排序又称“缩小增量排序”,该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
代码如下:6、快速排序快速排序(Quicksort)是对冒泡排序的一种改进。
由C. A. R. Hoare在1962年提出。
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
算法实验报告

算法实验报告算法实验报告引言:算法是计算机科学的核心内容之一,它是解决问题的方法和步骤的描述。
算法的设计和分析是计算机科学与工程中的重要研究方向之一。
本实验旨在通过对算法的实际应用和实验验证,深入理解算法的性能和效果。
实验一:排序算法的比较在本实验中,我们将比较三种常见的排序算法:冒泡排序、插入排序和快速排序。
我们将通过对不同规模的随机数组进行排序,并记录每种算法所需的时间和比较次数,以评估它们的性能。
实验结果显示,快速排序是最快的排序算法,其时间复杂度为O(nlogn),比较次数也相对较少。
插入排序的时间复杂度为O(n^2),比较次数较多,但对于小规模的数组排序效果较好。
而冒泡排序的时间复杂度也为O(n^2),但比较次数更多,效率相对较低。
实验二:图的最短路径算法在图的最短路径问题中,我们将比较Dijkstra算法和Floyd-Warshall算法的效率和准确性。
我们将使用一个带权有向图,并计算从一个顶点到其他所有顶点的最短路径。
实验结果表明,Dijkstra算法适用于单源最短路径问题,其时间复杂度为O(V^2),其中V为顶点数。
而Floyd-Warshall算法适用于多源最短路径问题,其时间复杂度为O(V^3)。
两种算法在准确性上没有明显差异,但在处理大规模图时,Floyd-Warshall算法的效率较低。
实验三:动态规划算法动态规划是一种通过将问题分解成子问题并记录子问题的解来解决复杂问题的方法。
在本实验中,我们将比较两种动态规划算法:0-1背包问题和最长公共子序列问题。
实验结果显示,0-1背包问题的动态规划算法可以有效地找到最优解,其时间复杂度为O(nW),其中n为物品个数,W为背包容量。
最长公共子序列问题的动态规划算法可以找到两个序列的最长公共子序列,其时间复杂度为O(mn),其中m和n分别为两个序列的长度。
结论:通过本次实验,我们对不同算法的性能和效果有了更深入的了解。
排序算法中,快速排序是最快且效率最高的;在图的最短路径问题中,Dijkstra算法和Floyd-Warshall算法分别适用于不同的场景;动态规划算法可以解决复杂的问题,并找到最优解。
三种排序及其比较报告

三种排序及其比较实验报告(1)、实验题目通过快速排序,折半排序,希尔排序三种方法进行排序数据,并统计每一种排序在过程中对整数的比较次数和移动次数,并输出结果。
(2)实验项目组成该程序由主函数main()和子函数quicksort(),shellsort(),binSort()组成。
(3)实验项目的程序结构:(4)函数的功能描述quicksort(int a[],int l,int r,int *u1,int *v1) 快速排序算法shellsort(int a[],int n) shell排序算法binSort(int a[],int n) 2分插入排序算法(5)实验数据与实验结果测试数据:在main()函数里面可以事先给定要排序的整数,这里给的是11,3,28,52,46,32,66,88 等 8个非顺序数据.实验结果见下图:(6)算法描述:#include "stdio.h"#include "conio.h"quicksort(int a[],int l,int r,int *u1,int *v1) /*快速排序*/ {int i,j,temp,k=0,u,v;i=l; j=r;temp=a[i];if(l>=r) return;while(i!=j){while(a[j]>=temp&&i<j) j--;*u1=*u1+1;if(i<j) { a[i]=a[j]; *v1=*v1+1; i++;}while(a[i]<temp&&i<j) i++;*u1=*u1+1;if(i<j) {a[j]=a[i];*v1=*v1+1;j--;}}a[i]=temp;quicksort(a,l,i-1,u1,v1);quicksort(a,i+1,r,u1,v1);}void shellsort(int a[],int n) /*希尔排序*/ {int d,i,j,x,y , temp,v;x=0; y=0 ;for(d=n/2;d>0;d=d/2){for(i=d;i<n;i++){temp=a[i];j=i-d;while(j>=0 && temp<a[j]){a[j+d]=a[j];y++;j=j-d;}x++ ;a[j+d]=temp;}}printf("\n the number of compare x=%d ",x);printf("\n the number of move y=%d\n ",y); for(v=0;v<=7;v++){ printf("%5d",a[v]);}printf("\n");}void binSort(int a[],int n) /* 折半插入排序 */ {int i,j,low,hight,mid,m=0,k =0 ;int v;int temp;for(i=1;i<n;i++){temp=a[i];low=0; hight=i-1;while(low<=hight){mid=(low+hight)/2;if (temp<a[mid])hight=mid-1;else low=mid+1;m++;}for(j=i-1;j>=low;j--)a[j+1]=a[j]; k++;if(low!=i) k++;a[low]=temp;}printf("the number of compare m=%d\n",m);printf("the number of move k=%d\n",k);for(v=0;v<=7;v++){ printf("%8d",a[v]); }}void main(){int i,j,k,v;int *u1=2,*v1 =0;int a[8]={11,3,28,52,46,32,66,88};int b[8]={11,3,28,52,46,32,66,88};int c[8]={11,3,28,52,46,32,66,88};printf("binSort\n");printf("\n");binSort(a,8);printf("\n");printf("shellSort\n");shellsort(b,8);printf("\n");printf("quickSort\n");printf("\n");quicksort(c,0,8,u1,v1);for(v=0;v<=7;v++){ printf("%5d",a[v]);}printf("\n the number of compare u1=%d ",*u1); printf("\n the number of move v1=%d \n ",*v1);getch();}。
数据结构实验报告-排序

数据结构实验报告-排序一、实验目的本实验旨在探究不同的排序算法在处理大数据量时的效率和性能表现,并对比它们的优缺点。
二、实验内容本次实验共选择了三种常见的排序算法:冒泡排序、快速排序和归并排序。
三个算法将在同一组随机生成的数据集上进行排序,并记录其性能指标,包括排序时间和所占用的内存空间。
三、实验步骤1. 数据的生成在实验开始前,首先生成一组随机数据作为排序的输入。
定义一个具有大数据量的数组,并随机生成一组在指定范围内的整数,用于后续排序算法的比较。
2. 冒泡排序冒泡排序是一种简单直观的排序算法。
其基本思想是从待排序的数据序列中逐个比较相邻元素的大小,并依次交换,从而将最大(或最小)的元素冒泡到序列的末尾。
重复该过程直到所有数据排序完成。
3. 快速排序快速排序是一种分治策略的排序算法,效率较高。
它将待排序的序列划分成两个子序列,其中一个子序列的所有元素都小于等于另一个子序列的所有元素。
然后对两个子序列分别递归地进行快速排序。
4. 归并排序归并排序是一种稳定的排序算法,使用分治策略将序列拆分成较小的子序列,然后递归地对子序列进行排序,最后再将子序列合并成有序的输出序列。
归并排序相对于其他算法的优势在于其稳定性和对大数据量的高效处理。
四、实验结果经过多次实验,我们得到了以下结果:1. 冒泡排序在数据量较小时,冒泡排序表现良好,但随着数据规模的增大,其性能明显下降。
排序时间随数据量的增长呈平方级别增加。
2. 快速排序相比冒泡排序,快速排序在大数据量下的表现更佳。
它的排序时间线性增长,且具有较低的内存占用。
3. 归并排序归并排序在各种数据规模下都有较好的表现。
它的排序时间与数据量呈对数级别增长,且对内存的使用相对较高。
五、实验分析根据实验结果,我们可以得出以下结论:1. 冒泡排序适用于数据较小的排序任务,但面对大数据量时表现较差,不推荐用于处理大规模数据。
2. 快速排序是一种高效的排序算法,适用于各种数据规模。
几种排序算法的平均性能比较(实验报告)

实验课程:算法分析与设计实验名称:几种排序算法的平均性能比较(验证型实验)实验目标:(1)几种排序算法在平均情况下哪一个更快。
(2)加深对时间复杂度概念的理解。
实验任务:(1)实现几种排序算法(selectionsort, insertionsort,bottomupsort,quicksort, 堆排序)。
对于快速分类,SPLIT中的划分元素采用三者A(low),A(high),A((low+high)/2)中其值居中者。
(2)随机产生20组数据(比如n=5000i,1≤i≤20)。
数据均属于范围(0,105)内的整数。
对于同一组数据,运行以上几种排序算法,并记录各自的运行时间(以毫秒为单位)。
(3)根据实验数据及其结果来比较这几种分类算法的平均时间和比较次数,并得出结论。
实验设备及环境:PC;C/C++等编程语言。
实验主要步骤:(1)明确实验目标和具体任务;(2)理解实验所涉及的几个分类算法;(3)编写程序实现上述分类算法;(4)设计实验数据并运行程序、记录运行的结果;(5)根据实验数据及其结果得出结论;(6)实验后的心得体会。
问题分析(包括问题描述、建模、算法的基本思想及程序实现的技巧等):选择排序:令A[1…n]为待排序数组,利用归纳法,假设我们知道如何对后n-1个元素排序,即对啊[A…n]排序。
对某个j,1<=j<=n,设A[j]是最小值。
首先,如果就!=1,我们交换A[1]和A[j]。
然后由假设,已知如何对A[2..n]排序,因此可对在A[2…n]中的元素递归地排序。
可把递归改为迭代。
算法程序实现如下:void SelectionSort(int *Array,int n,int &c){int i,j,k;int aa;c=0;for(i=0;i<n;i++){k=i;for(j=i+1;j<n;j++){c++;if(Array[j]<Array[k])k=j;}if(k!=i){aa=Array[i];Array[i]=Array[k];Array[k]=aa;}}}插入排序:将n个元素的数列分为已有序和无序两个部分,每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。
数据结构试验报告——各种内排序算法的实现及性能比较

实验报告(2010 / 2011 学年第 2 学期)课程名称数据结构——使用C++语言描述实验名称各种内排序算法的实现及性能比较实验时间2011年5月27日指导单位计算机科学与技术系指导教师学生姓名班级学号学院(系)专业一.实验目的和要求内容:验证教材的各种内排序算法。
分析各种排序算法的时间复杂度。
要求:使用随机数产生器产生大数据集合,运行上述各种排序算法,使用系统时钟测量各算法所需的实际时间,并进行比较。
二.实验环境(实验设备)Visual C++三.实验原理及内容单选择排序"<<endl;接插入排序"<<endl;泡排序"<<endl;速排序"<<endl;路合并排序"<<endl;排序"<<endl;出"<<endl;cout<<"PS:测试用的数组元素为"<<SIZE<<"时间为重复运行"<<TIMES<<"次的时间(包括了产生数据与析构的时间)"<<endl;this->switcha();}template <class T>void Menu<T>::childmenu(){cout<<"--------------------------------------------------------"<<endl;cout<<"1.最好情况"<<endl;cout<<"2.最坏情况"<<endl;cout<<"3.平均情况"<<endl;cout<<"4.返回主菜单"<<endl;cin>>b;if(b==4)this->printmenu();}template<class T>void Menu<T>::childmenu2(){cout<<"--------------------------------------------------------"<<endl;cout<<"1.原始算法"<<endl;cout<<"2.改进算法"<<endl;cout<<"3.返回主菜单"<<endl;cin>>c;if(c==3)this->printmenu();}template <class T>void Menu<T>::switcha(){<<endl;return 0;}/*ok--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok1简单选择排序直接用随机数据测试ok用时:请按任意键继续. . .--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok2直接插入排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单1ok用时:0请按任意键继续. . .直接插入排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单2ok用时:请按任意键继续. . .直接插入排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单3ok用时:请按任意键继续. . .直接插入排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单4--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok3冒泡排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单1ok用时:请按任意键继续. . .冒泡排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单2ok用时:请按任意键继续. . .冒泡排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单3ok用时:请按任意键继续. . .冒泡排序--------------------------------------------------------1.最好情况2.最坏情况3.平均情况4.返回主菜单4--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok4--------------------------------------------------------1.原始算法2.改进算法3.返回主菜单1原始快速排序直接用随机数据测试ok用时:请按任意键继续. . .--------------------------------------------------------1.原始算法2.改进算法3.返回主菜单2改进的快速排序直接用随机数据测试ok用时:请按任意键继续. . .--------------------------------------------------------1.原始算法2.改进算法3.返回主菜单3--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok5合并排序直接用随机数据测试ok用时:请按任意键继续. . .--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok6堆排序直接用随机数据测试ok用时:请按任意键继续. . .--------------------------------------------------------内排序测试系统--------------------------------------------------------1.简单选择排序2.直接插入排序3.冒泡排序4.快速排序5.两路合并排序6.堆排序7.退出PS:测试用的数组元素为400时间为重复运行1000次的时间(包括了产生数据与析构的时间)ok7Press any key to continue*/四.实验小结(包括问题解和解决方法、心得体会、意见与建议等)通过本次实验对教材上的各种内排序算法进行了逐一验证。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验课程:算法分析与设计实验名称:几种排序算法的平均性能比较(验证型实验)实验目标:(1)几种排序算法在平均情况下哪一个更快。
(2)加深对时间复杂度概念的理解。
实验任务:(1)实现几种排序算法(selectionsort, insertionsort,bottomupsort,quicksort, 堆排序)。
对于快速分类,SPLIT中的划分元素采用三者A(low),A(high),A((low+high)/2)中其值居中者。
(2)随机产生20组数据(比如n=5000i,1≤i≤20)。
数据均属于围(0,105)的整数。
对于同一组数据,运行以上几种排序算法,并记录各自的运行时间(以毫秒为单位)。
(3)根据实验数据及其结果来比较这几种分类算法的平均时间和比较次数,并得出结论。
实验设备及环境:PC;C/C++等编程语言。
实验主要步骤:(1)明确实验目标和具体任务;(2)理解实验所涉及的几个分类算法;(3)编写程序实现上述分类算法;(4)设计实验数据并运行程序、记录运行的结果;(5)根据实验数据及其结果得出结论;(6)实验后的心得体会。
问题分析(包括问题描述、建模、算法的基本思想及程序实现的技巧等):选择排序:令A[1…n]为待排序数组,利用归纳法,假设我们知道如何对后n-1个元素排序,即对啊[A…n]排序。
对某个j,1<=j<=n,设A[j]是最小值。
首先,如果就!=1,我们交换A[1]和A[j]。
然后由假设,已知如何对A[2..n]排序,因此可对在A[2…n]中的元素递归地排序。
可把递归改为迭代。
算法程序实现如下:void SelectionSort(int *Array,int n,int &c){int i,j,k;int aa;c=0;for(i=0;i<n;i++){k=i;for(j=i+1;j<n;j++){c++;if(Array[j]<Array[k])k=j;}if(k!=i){aa=Array[i];Array[i]=Array[k];Array[k]=aa;}}}插入排序:将n个元素的数列分为已有序和无序两个部分,每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。
算法程序实现如下:void InsertionSort(int *Array,int n,int &c){int i,j;int aa;c=0;for(i=0;i<n;i++){aa=Array[i];j=i-1;while(j>=0 && Array[j]>aa){c++;Array[j+1]=Array[j];j=j-1;}Array[j+1]=aa;}}自底向上合并排序:利用分治法思想,将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。
然后再把有序子序列合并为整体有序序列。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
算法程序实现如下:void Merge(int *A,int p,int q,int r,int &c){int *B=new int[r-p+1]; int s=p;int t=q+1;int k=0;while(s<=q && t<=r) {c++;if(A[s]<=A[t]){B[k]=A[s];s=s+1;}else{B[k]=A[t];t=t+1;}k=k+1;}if(s==q+1){while(t<=r){B[k]=A[t];k=k+1;t=t+1;}}else{while(s<=q){B[k]=A[s];k=k+1;s=s+1;}}k=0;while(p<=r){A[p]=B[k];k++;p++;}delete B;}void BottomupSort(int *Array,int n,int &c){int s,i, t=1;c=0;while(t<n){s=t;t=2*s;i=0;while(i+t<n){Merge(Array,i,i+s-1,i+t-1,c);i=i+t;}if(i+s<n)Merge(Array,i,i+s-1,n-1,c);}}快速排序:设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
快速排序就是递归调用此过程。
算法程序实现如下:void Split(int *A,int low,int high,int &w,int &c){int aa,x;int j,i=low;int mid=(low+high)/2;if(A[low]<A[high]){if(A[mid]<A[low])w=low;else if(A[mid]<A[high])w=mid;else w=high;}else{if(A[mid]<A[high])w=high;else if(A[mid]<A[low])w=mid;else w=low;}c++;x=A[w];aa=A[low];A[low]=A[w];A[w]=aa;for(j=low+1;j<=high;j++){c++;if(A[j]<=x){i=i+1;if(i!=j){aa=A[i];A[i]=A[j];A[j]=aa;}}}aa=A[low];A[low]=A[i];A[i]=aa;w=i;}void Quick(int *A,int low,int high,int &c){int w;if(low<high){Split(A,low,high,w,c);Quick(A,low,w-1,c);Quick(A,w+1,high,c);}}void QuickSort(int *Array,int n,int &c){c=0;Quick(Array,0,n-1,c);}堆排序:堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区,再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].ke y,由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。
然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n- 1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
…… 直到无序区只有一个元素为止。
void Siftdown(int *H,int n,int i,int &c){bool done=false;int j,a;if(2*i+1>n)return;while(2*i+1<=n && !done){j=i;i=2*i+1;c=c+2;if(i+1<=n && H[i+1]>H[i])i=i+1;if(H[j]<H[i]){a=H[i];H[i]=H[j];H[j]=a;}else done=true;}}void MakeHeap(int *A,int n,int &c){int i;for(i=(n-2)/2;i>=0;i--)Siftdown(A,n-1,i,c);}void HeapSort(int *A,int n,int &c){c=0;MakeHeap(A,n,c);int j;int x;for(j=n-1;j>=1;j--){x=A[0];A[0]=A[j];A[j]=x;Siftdown(A,j-1,0,c);}}实验数据及其结果(可用图表形式给出):输入规模n selection insertion bottomup quick Heap 5000 运行时间(毫秒)78 78 0 0 0 数组元素比较次数12497500 6200198 56813 63183 107744 10000 运行时间(毫秒)312 281 16 0 0 数组元素比较次数49995000 25208475 123658 138111 235424 20000 运行时间(毫秒)1263 1123 16 0 16 数组元素比较次数199990000 99750639 267476 302923 510812 30000 运行时间(毫秒)2870 2527 16 16 15 数组元素比较次数449985000 224979041 410268 460289 800366 40000 运行时间(毫秒)5210 4509 47 15 16 数组元素比较次数799980000 402537541 574791 663812 1101172 50000 运行时间(毫秒)8174 7004 47 16 31 数组元素比较次数1249975000 626068874 733390 866351 1409734实验结果分析及结论:选择排序算法最稳定,算法的效率只跟输入规模有关,与元素序列无关,但也是效率最差。
插入排序的效率跟元素的序列有关,最好情况(已排序)时间复杂度为0,最坏情况(逆序)时间复杂度为Θ(n2).自底向上合并排序、快速排序、堆排序的效率差不多,最坏情况和最好情况时间复杂度都为o(n㏒n),对于绝大部分元素有序的数组,这三种排序算法的效率不如插入排序。
实验自我评价及心得体会:通过这次实验,我对这五种排序的原理和执行过程有了更清楚地了解,由于本次实验是在VC++2008平台下利用MFC实现,在学习算法的过程中同时也让我更加熟悉了windows 的界面编程方法。
主要参考文献:《算法设计技巧与分析》[沙特]M.H.Alsuwaiyel 著。