題目:編寫“簡單選擇排序”和“堆排序”演算法,對它們在排序過程中的關鍵字比較次數和關鍵字移動次數進行比較。
測試資料:
(1)隨機產生100個測試資料;
(2)寫出測試結果。
插入元素,向上調整堆:
刪除元素後,向下調整堆:
4.調試分析
本程式一共實現了5種排序方法,可以選擇執行。
各種排序演算法中關鍵字的比較次數和交換次數是和要排序的資料的個數有關係的,如果在每一次的交換和比較之後計數統計(當然我試過了),雖然有準確的數字,但是不足以進行總體的分析。進行大量的資料排序的時候,我們考慮的是整體的效能,而非準確的比較了多少次,交換了多少次,所以我進行了畫出了排序演算法的流程圖,這對於分析關鍵字的比較次數和交換次數,更加直觀,也能從整體上分析。
本程式中的資料,在經過一次排序後,已經是有序的了,這時候如果接著進行下一個排序,很可能導致演算法的效能不能很好地發揮出來。所以,建議執行一次排序後,重新啟動程式,這樣會再次產生隨機的資料,進行排序。
5.使用說明
運行程式,按照提示即可。
6.測試結果
1、隨機產生10000個資料時,各個演算法的執行時間為:
直接插入排序,耗時141
堆排序,耗時0
冒泡排序,耗時500
直接選擇排序,耗時219
快速排序,耗時0
2、隨機產生100000個資料時,各個演算法的執行時間為:
直接插入排序,耗時15109
堆排序,耗時47
冒泡排序,耗時50000
直接選擇排序,耗時23297
快速排序,耗時16
可以看出,快速排序果然快,堆排序也不遜色,冒泡、直接插入、直接選擇隨著資料數量的增加,他們的耗時也是快速增長的。
7.附錄
來源程式檔案清單。
main.cpp#include "stdafx.h"#include <iostream>#include <stdlib.h>#include <time.h>#include <math.h>#include "MinHeap.h"using namespace std;#define DataType int#define N 100000DataType A[N];//輸出數組元素void Print(){for (int i=0;i<N;i++){cout<<"A["<<i<<"]="<<A[i]<<" ";}}//直接插入排序void InsertSort(DataType array[],int n){cout<<"直接插入排序"<<endl;int i,j;DataType temp;for ( i=0;i<n-1;i++){temp=array[i+1];j=i;while(j>=0 &&temp<array[j]){array[j+1]=array[j];j--;}array[j+1]=temp;}}//直接選擇排序,也叫簡單選擇排序void SelectSort(DataType array[],int n){cout<<"直接選擇排序"<<endl;int i,j,small;DataType temp;for (i=0;i<n;i++){small=i;for (j=i+1;j<n;j++){if (array[small]>array[j]){small=j;}}if (small!=i){temp=array[i];array[i]=array[small];array[small]=temp;}}}//堆排序,小頂堆void HeapSort(DataType array[],int n){cout<<"堆排序"<<endl;MinHeap H(array,n);//製成堆int i,j; DataType temp;for(i=n-1;i>0;i--){temp=H.Delete();array[i]=temp;}//反轉,換成從小到大的順序for (j=0;j<n/2;j++){temp=array[j];array[j]=array[n-1-j];array[n-1-j]=temp;}}//冒泡排序void BubbleSoort(DataType array[],int n){cout<<"冒泡排序"<<endl;int i,j,flag=1;DataType temp;for (i=1;i<n && flag==1;i++){flag=0;for (j=0;j<n-i;j++){if (array[j]>array[j+1]){flag=1;temp=array[j];array[j]=array[j+1];array[j+1]=temp;}}}}//快速排序void QuickSort(DataType array[],int low,int high){int i=low;int j=high;DataType temp=array[low];while(i<j){//從右往左while (i<j && temp<array[j]){j--;}if (i<j){array[i]=array[j];i++;}//從左往右while (i<j && array[i]<temp){i++;}if (i<j){array[j]=array[i];j--;}}array[i]=temp;if (low<i){QuickSort(array,low,i-1);}if (i<high){QuickSort(array,j+1,high);}}int _tmain(int argc, _TCHAR* argv[]){//cout<<N<<"個資料進行測試,依次為:"<<endl;//產生資料srand( (int)time( NULL ) );for (int i=0;i<N;i++){A[i]=rand();//cout<<"A["<<i<<"]="<<A[i]<<" ";}/*printf("/n/n%d 插入排序/n",1);printf("%d 堆排序/n",2);printf("%d 冒泡排序/n",3);printf("%d 選擇排序/n",4);printf("%d 快速排序/n",5);printf("/n非法輸入,程式將退出/n");printf("/n/n請選擇操作/n");int n;while(1){cin>>n;switch (n){case 1:InsertSort(A,N);cout<<"結果為:";Print();cout<<endl;break;case 2:HeapSort(A,N);cout<<"結果為:";Print();cout<<endl;break;case 3:BubbleSoort(A,N);cout<<"結果為:";Print();cout<<endl;break;case 4:SelectSort(A,N);cout<<"結果為:";Print();cout<<endl;break;case 5:QuickSort(A,0,N-1);cout<<"結果為:";Print();cout<<endl;break;default:exit(1);}}*/clock_t start,finish;start=clock();//InsertSort(A,N);//HeapSort(A,N);//BubbleSoort(A,N);//SelectSort(A,N);QuickSort(A,0,N-1);finish=clock();cout<<"耗時"<<double(finish-start)<<endl<<endl;system("pause");return 0;}MinHeap.h//小頂堆標頭檔#pragma once#include <iostream>#include <stdlib.h>#include <stdio.h>using namespace std;#define DataType intclass MinHeap{private:DataType *heapArray;//存放資料元素的數組int markArray;//標記int MaxHeapSize;//最大元素個數int heaapSize;//當前元素個數void FilterUp(int i);//插入元素後,調整的過程void FilterDown(int i);//刪除元素後,調整的過程public:int count_compare;//比較次數int count_move;//移動次數public:MinHeap(int maxSize);MinHeap(DataType arr[],int n);//拷貝建構函式,把n個元素調整make為堆void Insert(DataType &item);//插入元素DataType Delete();//刪除堆頂,即最小元素DataType GetHeapTop()//返回堆頂元素{return heapArray[0];}int HeapSize()//返回當前堆中元素的個數{return heaapSize;}int HeapEmpty()//堆是否為空白{return heaapSize==0;}int HeapFull()//堆是否已滿{return heaapSize==MaxHeapSize;}void Print();//輸出當前堆中的元素~MinHeap(void)//沒有標記的時候,刪除堆{if (markArray==0){delete heapArray;}//cout<<endl<<"堆排序。"<<"比較次數"<<count_compare<<" , 移動次數"<<count_move<<endl;}};MinHeap.cpp//小頂堆源檔案#include "StdAfx.h"#include "MinHeap.h"//製成堆,調整為堆MinHeap::MinHeap(int maxSize){if (maxSize<=0){//cout<<"參數非法";exit(1);}MaxHeapSize=maxSize;heaapSize=0;heapArray=new DataType[maxSize];markArray=0;count_compare=0;count_move=0;}//把數組製成堆,調整為堆MinHeap::MinHeap(int arr[], int n){if (n<=0){//cout<<"參數非法";exit(1);}this->count_compare=0;this->count_move=0;MaxHeapSize=n;heaapSize=n;heapArray=arr;int currentPos=(n-1)/2;while(currentPos>=0){FilterDown(currentPos);currentPos--;count_compare++;//比較了}count_compare++;//比較了markArray=1;}//插入元素後,調整堆void MinHeap::FilterUp(int i){int currentPos,parentPos;DataType target;currentPos=i;target=heapArray[i];parentPos=(i-1)/2;while(currentPos!=0){if (heapArray[parentPos]<=target){break;}else{heapArray[currentPos]=heapArray[parentPos];currentPos=parentPos;parentPos=(currentPos-1)/2;}}heapArray[currentPos]=target;//插入新元素}//插入新元素void MinHeap::Insert(DataType &item){if (heaapSize==MaxHeapSize){//cout<<"堆已滿";exit(1);}heapArray[heaapSize]=item;FilterUp(heaapSize);heaapSize++;}//刪除堆頂元素,調整void MinHeap::FilterDown(int i){int currenrPos,childPos;DataType target;currenrPos=i;target=heapArray[i];childPos=2*i+1;while(childPos<heaapSize){count_compare++;//比較了if ((childPos+1<heaapSize) && (heapArray[childPos+1]<=heapArray[childPos])){childPos=childPos+1;count_compare+=2;//比較了}if (target<=heapArray[childPos]){count_compare++;//比較了break;}else{heapArray[currenrPos]=heapArray[childPos];currenrPos=childPos;childPos=2*currenrPos+1;count_move++;//交換了}count_compare++;//比較了}count_compare++;//比較了heapArray[currenrPos]=target;}//刪除堆頂,即最小元素DataType MinHeap::Delete(){if (heaapSize==0){//cout<<"已空";exit(1);}DataType item=heapArray[0];heapArray[0]=heapArray[heaapSize-1];heaapSize--;count_move++;//交換了FilterDown(0);return item;}//輸出元素void MinHeap::Print(){for (int i=0;i<this->heaapSize;i++){printf("%d ",this->heapArray[i]);}}