冒泡排序,快速排序,堆排序比较(转自:http://linpder.blog.163.com/blog/static/487641020082124532971/)
2011-02-20 11:46
225 查看
一 问题描述
对一个较大规模的数组进行排序,分别使用冒泡,快速,和堆排序,比较这三种方法的效率.
二 算法分析与设计
三种算法要比较哪一个效率更高,必须使用相同的数组进行排序,而且数组的元素个数要相当大,这样才能够看处它们执行效率的差别。要输入一个很大的数组显然不符合现实,因为工程太庞大了,所以我们用随机产生函数:rang()来产生所要的数组,虽然每次产生的数组都不一样,但是随机性更能体现出一个算法执行的好和坏。我们并不是就执行一次,而是通过多次的执行得出结论。
数组产生了以后,接下来的事情就是用每一种排序方法对产生的数组进行排序,同时记录下排序所需要的时间,我们通过所花时间的多少来比较哪个算法的效率高。记录时间我们用:
t=clock()这个函数,开始排序的时间:t1=clock();和结束排序后的时间:t2=clock().两者相减得到:t=t2-t1,t就是所花的时间,t/CLOCKS_PER_SEC就把所花的时间转化为秒数。
这样,我们只要再程序运行的时候输入数组的大小,就可以通过不同的排序得出不同的排序所花的时间,从而得出比较的结果。
三 时间复杂度分析
冒泡排序的时间复杂度为: T(n) = O(n^2)
快速排序的时间复杂度为: T(n) = O(n*log n) (前面的报告中已经有分析说明)
堆 排序的时间复杂度为 : T(n) = O(n*log n) ( 在最坏的情况下)
堆排序的运行时间主要是耗费在建立初始堆和调整建立新堆的反复筛选上面,在建立初始堆的时候,需要的时间是0(n);因为在建初始堆的时候,调用Heapify() n/2次,有Heapify()所需要的时间可知道,当i在n/2的到n/4+1的范围内时,每次调用耗费时间为C,C为一常数,当i在n/4到n/8+1的范围内时,耗费的时间为2C,………。所以
C(n/4+2*n/8+3*n/16+……..)=O(n)
在调整堆的时候,调用Heapify共n-1次,每次调用所需要的时间为O(n)的时间,所以整个算法在最坏的情况下只需要:T(n) = O(n*log n) 的时间。
四 运行结果和分析
1)当数组的规模都为10000个元素的时候:
冒泡排序所需的时间是:0.625秒;快速排序和堆排序基本上不需要时间(因为规模比较小所以看不出来)。
2)当数组的规模都为100000个元素的时候:
冒泡排序所需要的时间为:69.875秒;
快速排序所需要的时间为:0.047 秒;
堆 排序所需要的时间为:0.031 秒;
从上面的比较不难看出堆排序要比快速好,快速又要比冒泡排序好。但这时候堆排序和快速排序所花的时间相差不时很多。
3)当数组规模为1000000个元素的时候:
这主要是比较快速排序和堆排序之间的差距,因为当规模这么大时,冒泡排序要花太多时间所以就没有进行比较测试。从结果中可以看到,当数组规模很大的时候,堆排序的优势就彻底的体现出来了,比快速排序要块很多。所以证明了一点,当数组元素很大的时候,用堆排序时最优的。
对一个较大规模的数组进行排序,分别使用冒泡,快速,和堆排序,比较这三种方法的效率.
二 算法分析与设计
三种算法要比较哪一个效率更高,必须使用相同的数组进行排序,而且数组的元素个数要相当大,这样才能够看处它们执行效率的差别。要输入一个很大的数组显然不符合现实,因为工程太庞大了,所以我们用随机产生函数:rang()来产生所要的数组,虽然每次产生的数组都不一样,但是随机性更能体现出一个算法执行的好和坏。我们并不是就执行一次,而是通过多次的执行得出结论。
数组产生了以后,接下来的事情就是用每一种排序方法对产生的数组进行排序,同时记录下排序所需要的时间,我们通过所花时间的多少来比较哪个算法的效率高。记录时间我们用:
t=clock()这个函数,开始排序的时间:t1=clock();和结束排序后的时间:t2=clock().两者相减得到:t=t2-t1,t就是所花的时间,t/CLOCKS_PER_SEC就把所花的时间转化为秒数。
这样,我们只要再程序运行的时候输入数组的大小,就可以通过不同的排序得出不同的排序所花的时间,从而得出比较的结果。
三 时间复杂度分析
冒泡排序的时间复杂度为: T(n) = O(n^2)
快速排序的时间复杂度为: T(n) = O(n*log n) (前面的报告中已经有分析说明)
堆 排序的时间复杂度为 : T(n) = O(n*log n) ( 在最坏的情况下)
堆排序的运行时间主要是耗费在建立初始堆和调整建立新堆的反复筛选上面,在建立初始堆的时候,需要的时间是0(n);因为在建初始堆的时候,调用Heapify() n/2次,有Heapify()所需要的时间可知道,当i在n/2的到n/4+1的范围内时,每次调用耗费时间为C,C为一常数,当i在n/4到n/8+1的范围内时,耗费的时间为2C,………。所以
C(n/4+2*n/8+3*n/16+……..)=O(n)
在调整堆的时候,调用Heapify共n-1次,每次调用所需要的时间为O(n)的时间,所以整个算法在最坏的情况下只需要:T(n) = O(n*log n) 的时间。
四 运行结果和分析
1)当数组的规模都为10000个元素的时候:
冒泡排序所需的时间是:0.625秒;快速排序和堆排序基本上不需要时间(因为规模比较小所以看不出来)。
2)当数组的规模都为100000个元素的时候:
冒泡排序所需要的时间为:69.875秒;
快速排序所需要的时间为:0.047 秒;
堆 排序所需要的时间为:0.031 秒;
从上面的比较不难看出堆排序要比快速好,快速又要比冒泡排序好。但这时候堆排序和快速排序所花的时间相差不时很多。
3)当数组规模为1000000个元素的时候:
这主要是比较快速排序和堆排序之间的差距,因为当规模这么大时,冒泡排序要花太多时间所以就没有进行比较测试。从结果中可以看到,当数组规模很大的时候,堆排序的优势就彻底的体现出来了,比快速排序要块很多。所以证明了一点,当数组元素很大的时候,用堆排序时最优的。
// 主程序 (.cpp文件) #include <stdio.h> #include <time.h> #include <stdlib.h> #include <malloc.h> #include <conio.h> #include "BobbleSort.h" #include "QuickSort.h" #include "HeapSort.h" int main() { int N; int *a; time_t start ,end; double usetime; int i,j; i=1; while(i<=3) { if(i==1) printf("--------------------冒 泡 排 序--------------------\n"); else if(i==2) printf("--------------------快 速 排 序--------------------\n"); else if(i==3) printf("-------------------- 堆 排 序 --------------------\n"); printf("输入数组元素N的值: "); scanf("%d",&N); if(i==3) a=(int *)malloc((N+1)*sizeof(int)); else a=(int *)malloc(N*sizeof(int)); if(!a)exit(1); srand(time(NULL)); if(i==3) for(j=1;j<=N;j++) a[j]=rand()%1000; else for(j=0;j<N;j++) a[j]=rand()%1000; start=clock(); if(i==1) BobbleSort(a,N); else if(i==2) QuickSort(a,0,N-1); else if(i==3) HeapSort(a,N); end=clock(); usetime=(end-start)*1.0/CLOCKS_PER_SEC; printf("该排序所花的时间为:"); printf("%lf 秒\n",usetime); free(a); i++; } getch(); return 0; } //********************************* BobbleSort.h文件 void BobbleSort(int a[],int N) //冒泡排序的算法 { int k,flag,m,j; flag=1; //设置一个标志位用来表示在每一轮的比较中是否有元素交换. m=N-1; while(flag>0) { flag=0; k=m; for(j=0;j<k;j++) if(a[j]>a[j+1]) { int t; t=a[j];a[j]=a[j+1];a[j+1]=t; flag=1; m=j; } } } //************************************* QuickSort.h文件 int Partion(int a[],int low,int high) //找出分割位置 { int key; key=a[low]; while(low<high) { while(low<high&&a[high]>=key)high--; a[low]=a[high]; while(low<high&&a[low]<=key)low++; a[high]=a[low]; } a[low]=key; return low; } void QuickSort(int a[],int low,int high) { int po; if(low<high) { po=Partion(a,low,high); QuickSort(a,low,po-1); //递归调用 QuickSort(a,po+1,high); } else return ; } //***************************************** HeapSort.h 文件 void swap(int &a,int &b) { a=a+b; b=a-b; a=a-b; } void Heapify(int a[],int k,int m) //整理堆 { int k1=2*k; int k2=2*k+1; if(k2<=m) { if((a[k1]>a[k2]&&a[k2]>a[k])||(a[k1]>a[k]&&a[k2]<a[k])) { swap(a[k1],a[k]); Heapify(a,k1,m); } else if((a[k1]<a[k2]&&a[k1]>a[k])||(a[k2]>a[k]&&a[k]>a[k1])) { swap(a[k2],a[k]); Heapify(a,k2,m); } } else if(k1<=m) { if(a[k1]>a[k]) { swap(a[k1],a[k]); Heapify(a,k1,m); } } else return ; } void HeapSort(int a[],int m) { int i; for(i=m/2;i>=1;i--) Heapify(a,i,m); for(i=m;i>1;i--) { swap(a[i],a[1]); Heapify(a,1,i-1); } }
相关文章推荐
- 冒泡排序,快速排序,堆排序比较(转自:http://linpder.blog.163.com/blog/static/487641020082124532971/)
- 随机生成30个数,试比较直接插入排序、简单选择排序、冒泡排序、快速排序、堆排序和希尔排序的时空性能和稳定性。
- 冒泡排序,快速排序,堆排序比较
- 插入排序、冒泡排序、选择排序、快速排序、堆排序、归并排序算法比较
- 几种常见的排序算法,选择排序,冒泡排序,希尔排序,堆排序,快速排序,归并排序,基数排序的比较
- 【更新】排序算法比较:插入排序,冒泡排序,归并排序,堆排序,快速排序,计数排序,基数排序,桶排序
- 比较排序总结——直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序
- 6种排序算法及其比较 简单选择排序,堆排序,简单插入排序,希尔排序,冒泡排序,快速排序,归并排序
- 冒泡排序,快速排序,堆排序比较
- 归并排序,快速排序,堆排序,冒泡排序 c语言源代码
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 快速排序、归并排序、堆排序三种算法性能比较
- leecode 169. Majority Element(C语言,快速排序,堆排序,各类排序算法复杂度比较)22
- 各种排序算法总结----基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)
- 冒泡排序、选择排序、堆排序、快速排序、插入排序算法复杂度分析与算法实现(自己总结与转)
- 冒泡排序、归并排序、快速排序、堆排序
- 快速排序、冒泡排序、堆排序、shell排序的递归和非递归实现
- 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)
- 【数据结构】常用比较排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)