当前位置:文档之家› 排序算法的比较

排序算法的比较

排序算法的比较1 课程设计名称 排序算法的比较概述 排序是计算机程序设计中的一种重要操作。

它的功能是将一个数据元素(或 记录)的任意序列,重新排列成一个按关键字有序的序列。

内部排序算法主要分 为5 大类,有十二个算法。

插入排序类、交换排序类、选择排序类、归并排序类 和基数排序类。

算法主要包括:插入排序、折半插入排序、选择排序、冒泡排序、 希尔排序、快速排序、堆排序、归并排序、基数排序等。

2 使用工具软件Microsoft Visual C++ 6.03 课程设计内容简介3.1 课程设计内容掌握各种排序算法(直接插入排序、冒泡排序、快速排序、简单选择排序)的思路核比较他们之间的优劣。

3.2 基本要求1.任意性:系统首先生成 1000 个随机整数,然后分别用不同的排序方法对 其进行升序排序,给出每种方法的比较次数或所用时间 2.友好性:界面要友好,输入有提示,尽量展示人性化 3.可读性:源程序代码清晰、有层次 4.健壮性:用户输入非法数据时,系统要及时给出警告信息3.3 课程设计思想程序设计的总体思路:首先构建 main()函数,根据题目的要求,再分 别构建四个排序函数:冒泡排序函数(long Bubblesort(long R[], long n)) 、 选择排序函数(long selectsort(long R[],long n)) 、直接插入排序函数(long insertsort(long R[], long n) ) 和 快 速 排 序 函 数 ( void QuickSort(long R[],long n) ) 。

为了使程序具有可读性和层次感,建立一个导航函数( void DaoHang()) 和操作函数 (void operate(long a[], long n)) , 其中, void DaoHang() 用来告知用户程序的操作流程,void operate(long a[], long n)用来接收用户 不同的选择,从而调用其它函数。

3.4 程序分析3.4.1 存储结构 顺序存储结构(如图 1) 示意图 a0 a1 a2 图1 3.4.2 关键算法分析 关键算法 1 实现四种算法的基本排序功能 1.冒泡排序:两两比较相邻记录的关键码,如果反序则交换,直到没有反序 记录为止。

实现过程(如图 2) 。

对于数组(21 25 49 16 08) 。

初态: 21 第一趟: 25 49 16 08 a3 a421 第二趟: 21 第三趟: 16 第四趟: 082516084916082549082125491621图225492.选择排序:从待排序的记录序列中选择关键码最小(或最大)的记录并将 它与序列中的第一个记录交换位置; 然后从不包括第一个位置上的记录序列中选 择关键码最小(或最大)的记录并将它与序列中的第二个记录交换位置;如此重 复,直到序列中只剩下一个记录为止。

实现过程(如图 3) 。

对于数组(21 25 49 16 08) 。

初态: 21 第一趟: 08 第二趟: 08 第三趟: 08 16 21图325491608254916211649252125493. 直接插入排序: 依次将待排序的序列中的每一个记录插入到先前排序好的 序列中,直到全部记录排序完毕。

实现过程(如图 4) 。

对于数组(21 25 49 16 08) 。

初态: 21 第一趟: 21 第二趟: 21 25 49 16 08 25 49 16 08 25 49 16 08第三趟: 21 第四趟: 16 第五趟: 08 16 21图4254916082125490825494.快速排序:首先选择一个基准,将记录分割为两部分,左支小于或等于基 准,右支则大于基准,然后对两部分重复上述过程,直至整个序列排序完成。

实现过程(如图 5) 对于数组(21 25 49 16 08) 。

初态: R[0]=21 21 low 第一趟: R[0]=21 08 R[0]=21 08 25 low R[0]=21 08 R[0]=21 08 R[0]=21 08 16 49 49 25 16 49low25491608 high25 low491608 high4916high2516 low491625high16high25R[0]=21 low=high 08 关键算法二 获取当前系统时间,精确到毫秒,分别在代码运行前后调用记录前后时间, 再相减即可得到代码运行时间。

//以冒泡排序为例 start=(double)clock();//开始 Bubblesort(R, n); end=(double)clock();//结束 Time = (double)(end-start)/CLK_TCK;//相减,精确到毫秒 关键算法三: 实现手动与计算机随机双重输入。

手动输入检查程序的正确性,计算机随即 输入,可以比较各排序算法的性能。

void Rand()//随机数函数 void HandInput()//手动输入函数 关键算法四 纠错功能。

在用户输入非法数据时,给予警告,并要求用户重新输入,不必 重启程序。

16low high21图549253.4.3 时间复杂度与空间复杂度: 理论分析可以得出各种排序算法的时间复杂度和空间复杂度,如下表所示 (图6) :排序方法平均情况最好情况最坏情况辅助空间直接插入排序O(n2)O(n)O(n2)O(1)起泡排序O(n2)O (n)O(n2)O(1)快速排序O(nlog2n)O(nlog2n)O(n2)O(log2n) ~O(n)简单选择排序O(n2)O(n2)图6O(n2)O(1)3.4.4 选择排序算法的依据 影响排序的因素有很多, 平均时间复杂度低的算法并不一定就是最优的。

相 反,有时平均时间复杂度高的算法可能更适合某些特殊情况。

同时,选择算法还 得考虑它的可读性, 以利于软件的维护。

一般而言, 需要考虑的因素有以下4 点:  待排序的记录数目n 的大小。

 记录本身数据量的大小,也就是记录中除关键字外的其他信息量的 大小。

 关键字的结构及其分布情况。

 对排序稳定性的要求。

3.5 程序流程图main()输入错误判断手动还是随 机输入(1,2)?2 1HandInput() (手动输入)Rand(); (随机输入)cin>>a[i] ;//数据存储void DaoHang()void operate()输入错误选择排序 方法 输入 0输入 a输入排序方法 结束 Void print()图73.6 运行环境Microsoft Visual C++ 6.0/WIN32 Console Application3.7 运行结果3.7.1 当手动输入五个数据时,运行结果(如图 8)图83.7.2 当选择随机数时,运行结果(如图 9)图93.8 得意之处得意之处 1 将时间精确到毫秒,使得实验结果更容易观察比较。

代码如下(冒泡排序为例) : start=(double)clock(); degree = Bubblesort(R, n);end=(double)clock(); Time = (double)(end-start)/; 其中 CLK_TCK 值为 1000,即将时间精确到毫秒(图 10) 。

图 10得意之处 2 将排序过程的每一趟输出,并且将已排好序的用中括号括起来,这样以来, 可以直接看出排序过程是否正确以及深入了解排序过程的每一步。

如:对于冒泡排序(图 11)图 11得意之处 3 冒泡排序算法中,运用做标记的方法,使得排序得到正确结果后,便停止做 不必要的循环。

代码如下 while(i>1) { long lastExchangeIndex=1;//表示已经有序 for(long j=1;j<i;j++) if(R[j+1]<R[j]) { long t=R[j]; R[j]=R[j+1]; R[j+1]=t; BT++; lastExchangeIndex=j;//记下进行的位置 } i=lastExchangeIndex;//本趟进行过交换的最后一个记录的位置 }4 课程设计中目前存在问题1.交换次数统计不够精确。

2.无论时间还是移动次数,应该有一个对比结果,不能只是罗列出来。

3.对于快速排序,存在两个问题。

其一,不能两边同时进行排序,使得排序趟数增加;其二,没能格式化输出,使得输出不清晰,不美观。

5 自我感受1.在初期构思代码的时候,首先构造了各种算法的基本实现代码,已经能够实现四种排序的基本功能,并且测试无误。

后来考虑能否优化本程序,首先考虑到测试算法的需求,需要大量随机数,因为增添了随机函数发生函数,满足各种测试条件的需求。

之后考虑如何能简化代码以实现多达四种排序算法的简单调用和性能指标统计、算法时间的精确而简易的统计、算法移动次数和比较次数的精确统计。

调用精确的系统函数实现时间的统计。

此外还添加了一系列优化,使得程序的结构变得更加合理,版面风格也变得好看,可读性增强。

2.程序的优化是一个艰辛的过程,如果只是实现一般的功能,将变得容易很多,当加上优化,不论是效率还是结构优化,都需要精心设计。

这次做优化的过程中,遇到不少阻力。

因而以后要多花力气学习C++编程语言,必须要加强这方面的训练,这样才能在将编程思想和数据结构转换为代码的时候能得心应手。

3.这次课设通过在网上查阅大量资料、程序以及一些学术论文,很好的对内排序算法进行了研究,特别对数据结构这门课所学到的内容付诸于实践,加深了理解。

另外,还学到了一写别的方面的知识。

这次课设做还有许多没有考虑周到的地方,希望老师指出。

6参考文献[1] 严蔚敏吴伟民,数据结构(C语言版),北京:清华大学出版社,2007。

[2] 汪祖柱沈晓潞,基于C语言实现的若干排序算法和分析,安徽电气工程职业学院学报,第九卷第一期。

[3] 王莉,常用内部排序算法的比较与选择,软件导刊,2006年1月号。

[4] 赵延惠,排序方法及效率浅析,思茅师范高等专科学校学报,第18卷附录:程序#include <iostream>#include<stdio.h>#include <stdlib.h>#include <time.h>#include <iomanip>#define MAX 100000000using namespace std;void print(long R[],long n){for(int i=1;i<=n;i++)cout<<setw(4)<<R[i];}//------------------------------------------------------------------------------//冒泡排序//------------------------------------------------------------------------------long Bubblesort(long R[], long n){long y=1;long i,BT=0;i=n;while(i>1){long lastExchangeIndex=1;//表示已经有序for(long j=1;j<i;j++)if(R[j+1]<R[j]){long t=R[j];R[j]=R[j+1];R[j+1]=t;BT++;lastExchangeIndex=j;//记下进行的位置}i=lastExchangeIndex;//本趟进行过交换的最后一个记录的位置cout<<"第"<<y<<"趟:";y++;for(long x=1;x<=i;x++)cout<<setw(4)<<R[x];cout<<setw(3)<<"["<<R[i+1];for(x=i+2;x<=n;x++)cout<<setw(4)<<R[x];cout<<"]";cout<<endl;}return BT;}//------------------------------------------------------------------------------//选择排序//------------------------------------------------------------------------------//static long ST=0;long SelectMinKey(long R[],long i,long n)//在R[i..R.length] 中选择关键字最小的记录{long temp=i;//记录最小的元素值的位置for(int j=i;j<=n;j++){if(R[temp]>R[j]){temp=j;//ST++;}}return temp;}long selectsort(long R[],long n){long j,i,t;long y=1;int ST=0;for( i=1;i<n;i++){j = SelectMinKey(R,i,n);// 在L.r[i..L.length] 中选择关键字最小的记录if (i!=j) // 与第i 个记录交换{t=R[i];R[i]=R[j];R[j]=t;ST++;}cout<<"第"<<y<<"趟:"<<' ';y++;for(long x=1;x<=i;x++)cout<<setw(4)<<R[x];cout<<setw(3)<<"["<<R[i+1];for(x=i+2;x<=n;x++)cout<<setw(4)<<R[x];cout<<"]";//print(R,n);cout<<endl;}return ST;}//------------------------------------------------------------------------------ //直接插入排序//------------------------------------------------------------------------------ long insertsort(long R[], long n){long y=1;long IT=0,j;for(long i=2;i<=n;++i){if(R[i]<R[i-1]){R[0]=R[i];//复制为哨兵IT=IT+1;for( j=i-1;R[0]<R[j];--j){R[j+1]=R[j];//记录后移IT=IT+1;}R[j+1]=R[0];//插入到正确位置IT=IT+1;}cout<<"第"<<y<<"趟:"<<' ';y++;cout<<setw(4)<<"["<<R[1];for(long x=2;x<=i;x++)cout<<setw(4)<<R[x];cout<<"]";for(x=i+1;x<=n;x++)cout<<setw(4)<<R[x];cout<<endl;}return IT;}//------------------------------------------------------------------------------ // 快速排序//------------------------------------------------------------------------------ static long QT=0;int Partition (long R[], long low, long high,long n){R[0] =R[low];long pivotkey = R[low]; // 枢轴QT=QT+2;while (low<high){while(low<high&& R[high]>=pivotkey)// 从右向左搜索-- high;R[low] = R[high];QT=QT+1;while (low<high && R[low]<=pivotkey)// 从左向右搜索++ low;R[high] = R[low];}QT=QT+1;R[low] =R[0];QT=QT+1;return low;}// Partitionvoid quicksort (long R[], int low, int high,long n,long y)// 对记录序列L.r[low..high]进行快速排序{if (low < high) // 长度大于1{long pivotloc = Partition(R,low,high,n);// 对L.r[low..high] 进行一次划分QT=QT+1;cout<<"第"<<y<<"趟:";y++;print(R,pivotloc-1);cout<<setw(2)<<"["<<R[pivotloc];cout<<"]";for(long x=pivotloc+1;x<=n;x++)cout<<setw(5)<<R[x];cout<<endl;quicksort(R, low, pivotloc-1,n,y); // 对低子序列递归排序quicksort(R, pivotloc+1, high,n,y); // 对高子序列递归排序}} // QSortvoid QuickSort(long R[],long n){long y=1;quicksort(R,1,n,n,y);}//------------------------------------------------------------------------------ //操作选择函数//------------------------------------------------------------------------------ void operate(long a[], long n){void main();long * R = new long [n];time_t start, end;//定义两个变量double Time;//排序时间long degree;//排序次数char ch;cout << "请选择排序算法:\t";cin >> ch;switch(ch){case '1':{cout<<'\n';cout<<"\t==您选择的是冒泡排序=="<<'\n';for(int i = 1; i <=n; i ++)//将随机数付给R[i]{R[i] = a[i];}start=(double)clock();degree = Bubblesort(R, n);end=(double)clock();Time = (double)(end-start)/CLK_TCK;//print(R,n);cout << '\n';cout << "冒泡排序所用时间:\t" << Time << '\n';cout << "冒泡排序交换次数:\t" << degree << '\n';cout<<'\n';operate(a, n);break;}case '2':{cout<<'\n';cout<<"\t==您选择的是选择排序=="<<'\n';for(int i = 1; i <= n; i ++){R[i] = a[i];}start=(double)clock();degree = selectsort(R, n);end=(double)clock();Time = (double)(end-start)/CLK_TCK;//print(R,n);cout<<'\n';cout << "选择排序所用时间:\t" << Time << '\n';cout << "选择排序交换次数:\t" << degree << '\n';cout << '\n';operate(a, n);break;}case '3':{cout<<'\n';cout<<"\t==您选择的是直接插入排序=="<<'\n';for(int i=1; i<=n; i ++){R[i] = a[i];}start=(double)clock();degree = insertsort(R, n);end=(double)clock();Time = (double)(end-start)/CLK_TCK;//print(R,n);cout<<'\n';cout << "直接插入排序所用时间:" << Time<< '\n';cout << "直接插入排序交换次数:" << degree << '\n';cout << '\n';operate(a, n);break;}case '4':{cout<<'\n';cout<<"\t==您选择的是快速排序=="<<'\n';for(int i=1; i<=n; i ++){R[i] = a[i];}start=(double)clock();QuickSort(R, n);end=(double)clock();Time = (double)(end-start)/CLK_TCK;cout<<'\n';cout << "快速排序所用时间:\t" << Time << '\n';cout << "快速排序交换次数:\t" << QT << '\n';cout << '\n';operate(a, n);break;}case 'a':{main();break;}default:{cout << "输入错误,请选择正确的操作!" << '\n';operate(a, n);break;}case '0':{cout<<"您已选择退出程序,谢谢使用"<<'\n';break;}}}//------------------------------------------------------------------------------//导航菜单函数//------------------------------------------------------------------------------void DaoHang(){cout<<"\n** 排序算法比较**"<<endl;cout<<"*****************************************************"<<endl;cout<<"== 1 --- 冒泡排序=="<<endl;cout<<"== 2 --- 选择排序=="<<endl;cout<<"== 3 --- 直接插入排序=="<<endl;cout<<"== 4 --- 快速排序=="<<endl;cout<<"== 0 --- 退出程序cout<<"== a --- 改变随机数的个数=="<<endl; cout<<"*****************************************************"<<endl; }//--------------------------------------------------------------------------------//随机输入函数//--------------------------------------------------------------------------------void Rand(){cout << "\n请输入要产生的随机数的个数(0<=n<=100000000):"<<endl;long int n;cin >> n;cout << endl;long *a = new long [n];srand((unsigned long)time(NULL));//产生一个以当前时间开始的随机种子for (long i=1; i<=n; i++){a[i] = rand() % n;//n为最大值,其随机域为0~n-1}DaoHang();print(a,n);operate(a, n);}//--------------------------------------------------------------------------------//手动输入函数//--------------------------------------------------------------------------------void HandInput(){cout<<"请输入数据个数:"<<endl;int n;cout<<"n=";cin>>n;cout << endl;long *a = new long [n];for (long i=1; i<=n; i++){cin>>a[i] ;}DaoHang();operate(a, n);}//------------------------------------------------------------------------------//------------------------------------------------------------------------------ void main(){loop:cout<<"手动输入请按1 ,随机输入请按2 "<<endl;int x;cin>>x;switch(x){case 2:{Rand();break;}case 1:{HandInput();break;}default:cout<<"输入错误,请重新输入!"<<endl;goto loop;}}。

相关主题