一 問題描述 對一個較大規模的數組進行排序,分別使用冒泡,快速,和堆排序,比較這三種方法的效率.
二 算法分析與設計 三種算法要比較哪一個效率更高,必須使用相同的數組進行排序,而且數組的元素個數要相當大,這樣才能夠看處它們執行效率的差別。要輸入一個很大的數組顯然 不符合現實,因爲工程太龐大了,所以我們用隨機產生函數: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); } }