一.基本概念
1.穩定排序與不穩定排序:
對於A,B兩個鍵值相等的對象,且在排序前,A在B之前,如果排序后A肯定還在B之前,則為穩定排序,如果B可能在A之前,為不穩定排序。
2.內排序和外排序:
內排序是指在排序期間數據對象全部存放在內存的排序
外排序是指在排序期間數據對象太多,不能同時存放在內存,必須依照排序過程的要求,不斷在內外存之間移動的排序。
二.各種排序算法的實現
1.插入排序
基本思想:插入第i個對象時前i-1個對象已經排好了,將第i個對象插入前i-1個對象的合適地方,使得前i個對象有序。是穩定排序,比較次數和移動次數復雜度都為O(n^2)
void insertSort(int* disorder, int size){ int temp = 0,i = 0; for(int j = 1; j < size; j++){ temp=disorder[j]; i = j; while(i > 0 && temp < disorder[i-1]){ disorder[i] = disorder[i-1]; i--; } disorder[i] = temp; } }
2.希爾排序
基本思想:將數列以gap作為間隔分成子序列,分別對子序列進行插入排序,再逐步縮小間隔進行插入排序。shell提出gap取floor(n/2),gap=floor(gap/2).這是一種不穩定的排序。
void shellSort(int* disorder, int size){ int gap = size / 2; int temp = 0, i = 0; while(gap > 0){ for(int g = 0; g < gap; g++){ for(int j = g + gap; j < size;){ temp = disorder[j]; i = j; while(i>gap-1 && temp<disorder[i-gap]){ disorder[i] = disorder[i-gap]; i=i-gap; } disorder[i]=temp; j=j+gap; } } gap=gap/2; } }
3.起泡排序
基本思想:依次比較key(n)和key(n-1),直到key(2)和key(1),這樣會使最小的對象被起泡到第一個,依次進行起泡,完成排序。是穩定排序,比較次數和移動次數復雜度都為O(n^2)
void bubbleSort(int* disorder, int size){ int temp=0,modified=0; for(int j=1;j<size;j++){ modified=0; for(int i=size-1;i>j-1;i--){ if(disorder[i]<disorder[i-1]){ temp = disorder[i]; disorder[i] = disorder[i-1]; disorder[i-1]=temp; modified++; } } if(modified==0){ break; } } }
4.快速排序
基本思想:任取一個對象作為基准,按照關鍵碼的大小,將排序隊列分為左右兩個子序列,小於該對象的都放在左序列,大於該對象的都放在右序列,然后分別對兩個子序列重復上述方法,直到所有對象有序排列。是不穩定排序,比較次數和移動次數復雜度都為O(n*logn)
void quickSort1(int* disorder, int start, int end){ if(start>=end){ return; } int middle=disorder[start]; int temp=0; int pivotpos=start+1,i=start+1; for(;i<=end;i++){ if(disorder[i]<middle){ if(i!=pivotpos){ temp=disorder[i]; disorder[i]=disorder[pivotpos]; disorder[pivotpos]=temp; } pivotpos++; } } disorder[start]=disorder[pivotpos-1]; disorder[pivotpos-1]=middle; quickSort1(disorder,start,pivotpos-2); quickSort1(disorder,pivotpos,end); } void quickSort(int* disorder, int size){ quickSort1(disorder,0,size-1); }
5.選擇排序
基本思想:每一趟在后面n-i個待排序對象中選出關鍵碼最小的對象,作為有序對象集的第i個對象。不穩定的排序,比較次數為O(n^2),移動次數為O(n)
void selectSort(int* disorder, int size){ int temp=0,small; for(int j=0;j<size-1;j++){ temp=disorder[size-1]; small=size-1; for(int i=size-2;i>j-1;i--){ if(disorder[i]<temp){ temp=disorder[i]; small=i; } } disorder[small]=disorder[j]; disorder[j]=temp; } }
6.錦標賽排序
基本思想:利用勝者樹來進行選擇排序。穩定的排序,比較次數為O(n*logn).
錦標賽排序雖然節省時間,但是對空間有較大浪費,不推薦
7.堆排序
基本思想:利用最大堆,將得到的最大元素依次調整到最后。不穩定的排序,時間復雜度為O(n*logn).
void filterDown(int* disorder, int pos, int size) { int temp = disorder[pos]; int iPos = pos; int iChildPos; while(2*iPos+1 < size){ iChildPos = 2*iPos+1; if(iChildPos+1<size && disorder[iChildPos+1] > disorder[iChildPos]){ iChildPos++; } if(temp<disorder[iChildPos]){ disorder[iPos] = disorder[iChildPos]; iPos = iChildPos; } else{ break; } } disorder[iPos] = temp; } void heapSort(int* disorder, int size) { for(int i=size/2-1; i>=0; i--){ filterDown(disorder, i, size); } int temp; for(int i=size-1; i>0; i--){ temp = disorder[i]; disorder[i] = disorder[0]; disorder[0] = temp; filterDown(disorder, 0, i); } }
8.歸並排序
基本思想:先兩兩排序,再逐步進行歸並。穩定的排序,時間復雜度為O(n*logn).
void merge(int* source,int*dest, int gap, int size){ int pos1,pos2,end1,end2,destpos=0; for(int i=0;i<size;i+=2*gap){ pos1=i; end1=i+gap>size?size:i+gap; pos2=i+gap; end2=i+2*gap>size?size:i+2*gap; while(pos1<end1&&pos2<end2){ if(source[pos1]<source[pos2]){ dest[destpos]=source[pos1]; pos1++; } else{ dest[destpos]=source[pos2]; pos2++; } destpos++; } while(pos1<end1){ dest[destpos++]=source[pos1++]; } while(pos2<end2){ dest[destpos++]=source[pos2++]; } } } void mergeSort(int* disorder, int size){ int gap=1; int* temparr= new int[size]; while(gap<size){ merge(disorder, temparr,gap,size); gap*=2; merge(temparr,disorder,gap,size); gap*=2; } delete[] temparr; }
9.基數排序
基本思想:利用分配和收集的方法進行排序,比如已知數字不超過100,可以按照十位數先進行分配,再分別進行排序后將數字收集起來。
三.排序結果的檢驗
對於排序算法,可以用下列的方法來生成一系列的隨機數進行排序,並用isSorted函數來檢驗是否正確的排序了。
bool isSorted(int* disorder, int size){ for(int i=0;i<size-1;i++){ if(disorder[i]>disorder[i+1]) return false; } return true; } int _tmain(int argc, _TCHAR* argv[]) { const int size=200; const int maxnum = 10000; int* disorder=new int[size]; srand((unsigned) time(NULL)); for(int i=0;i<size;i++){ disorder[i]=rand()%maxnum; } mergeSort(disorder,size); for(int i=0;i<size;i++){ cout<<disorder[i]<<endl; } cout<<isSorted(disorder,size)<<endl; return 0; }
