Algorithm——1.排序.md
排序算法
交換類排序:冒泡排序、快速排序
選擇類排序:簡單選擇排序、堆排序
插入類排序:直接插入排序、希爾排序
歸并類排序:歸并排序遞歸實現與非遞歸實現
交換類排序
交換類排序:冒泡排序、快速排序
冒泡排序
冒泡排序(Bubble Sort),排序的基本思想為兩兩比較小相鄰數據的關鍵字,如果順序為反則進行交換,直到沒有反序的記錄為止。
冒泡排序有多種變化,其三種不同實現的代碼如下:
//OS:Win | Terminal:Cmder | Editor:Atom | Language:cvoid Swap(int *a , int *b){int temp = *a;*a = *b;*b = temp; }//最容易的排序,從第一個元素開始向后與每一個元素進行比較,交換得到最小的元素,放在第i個位置 //這樣排序進行較多次無用的比較,當然,這并不是所謂的冒泡排序 void SimpleBubble(int array[] , int length){for(int i = 0 ; i < length ; i++){for(int j = i+1 ; j < length ; j++){if(array[i] > array[j]){Swap(&array[i],&array[j]);}}} }//從第一個位置開始,由下往上兩兩元素進行比較,判斷并交換得到最小值 //這樣排序依次循環確定第i個位置的元素 void LittleBubble(int array[] ,int length){for(int i =0 ; i < length ; i++){for(int j = length -1 ; j > i ;j --){if(array[j] < array[j-1]){Swap(&array[j],&array[j-1]);}}} }//增加標志位isSwap來表示是否存在反序或者是否進行過交換操作 //直到序列沒有反序記錄為止 void BubbleSort(int array[] , int length){int isSwap = 1;for(int i = 0 ; i < length ; i ++){if(isSwap){isSwap = 0;for(int j = length -1 ; j > i ; j --){if(array[j] < array[j-1]){Swap(&array[j],&array[j-1]);isSwap = 1;}}}} }void Print(int array[] , int length){for (int i = 0 ; i < length ;i++){printf(" %d",array[i]);} }int main(){int array[] = {6,5,3,1,0,2,9,8,4,7};BubbleSort(array,10);Print(array,10);return 0; }快速排序
快速排序(Quick Sort)是在實踐中最快的已知排序算法,平均運行時間是O(N log N)。快速排序之所以快是因為其精煉的、高度優化的內部循環。最壞情況的性能為O(N2),如今高度優化后的快速排序簡單易懂并且不難證明。
和歸并排序一樣,快速排序也是一種分治的遞歸算法。
將數組array進行快速排序QuickSort的基本算法由以下簡單的四步組成:
- 1.如果數組長度為0或者1,則直接返回;
- 2.使用Median3或其他方法獲取樞紐元素pivot;
- 3.劃分子集;
- 4.遞歸調用QuickSort
其中,Quick_Sort()中的外層while循環也可以寫成for循環,代碼如下:
void Quick_Sort(int array[] , int left ,int right){if(left >= right)return;int pivot = Median3(array,left,right);int i = left, j = right-1;for( ; ; ){if(i>=j)break;while(array[++i] < array[pivot]){}while(array[--j] > array[pivot]){}if(i<j)Swap(&array[i],&array[j]);elsebreak;}Swap(&array[i],&array[pivot]);Quick_Sort(array,left,i-1);Quick_Sort(array,i+1,right); }選擇類排序
選擇類排序:簡單選擇排序、堆排序
簡單選擇排序
簡單選擇排序(Simple Selection Sort),基本思想是:標記第i個元素為最小值下標min開始向后進行遍歷比較,不斷更新最小值下標min,結束該次循環后判斷min是否改變,若改變即交換i位置元素及min位置的最小元素。
void SelectSort(int array[] , int length){int min;for(int i = 0 ; i <length ; i++){min = i ; //Notice1:以第一個元素為最小開始向后遍歷比較for(int j = i+1 ; j < length ; j++){ //Notice2:j從i+1開始向后遍歷if(array[j] < array[min]){ //Notice3:每次都是array[j]與array[min]進行比較,來確定和更新最小值所在下標min = j;}}if(min != i){Swap(&array[i] ,&array[min]);}} }堆排序
堆排序(Heap Sort)是一個非常穩定的算法,排序平均使用的比較只比最壞情況界指出的略少。
void AdjustHeap(int array[] , int i , int length){//Notice2:保存開始節點的值為temp,減少直接交換的次數int temp = array[i];for(int j = i*2 +1 ; j <length ; j = j*2+1){if(j+1 < length && array[j] < array[j+1])j++;if(array[j] < temp ) //Notice3:循環對temp中保存的值進行比較break;array[i] = array[j];i = j;}array[i] = temp; //Notice4:最后在temp合適的位置上進行賦值放置 }void HeapSort(int array[] ,int length){//Notice1:首先從最后一個非頁子節點開始,由右向左、由下至上開始進行最大堆的構造for(int i = length/2 ; i >= 0 ; i --){AdjustHeap(array , i ,length);}for(int i = length -1 ; i > 0 ; i --){Swap(&array[0],&array[i]);AdjustHeap(array, 0, i );} }插入類排序
插入類排序:直接插入排序、希爾排序
直接插入排序
直接插入排序(Straight Insertion Sort)是最簡單的排序算法之一,主要思想是保證位置0到第i-1位置上的元素為已排序狀態,即插入排序利用這樣的事實,從i位置循環進行排序。
void InsertionSort(int array[] , int length ){int i,j,temp;//Notice1:開始以第一個數據為有序序列,從第二個數據開始排序for(i = 1 ; i <length ; i++){if(array[i] < array[i-1]){ //Notice2:當當前數據大于前一個時,開始向前插入temp = array[i]; //保存此時的值,為前方較大元素空出位置for(j = i -1 ; j>=0 && array[j] > temp ; j--){ //向前循環直至下標小于0,或者值比當前值更小array[j+1] = array[j]; //依次后移}array[j+1] = temp; //此時j位置的元素小于當前值,所以插入其后一位j+1即可}} }希爾排序
希爾排序(Shell Sort)是沖破二次時間屏障的第一批算法之一。主要思想是:通過比較一定間隔的元素來工作;各趟比較所用的距離(希爾增量)隨著算法的進行而逐漸減小,直到比較相元素的最后一趟排序為止。因此,希爾排序也稱為縮小增量排序。
void ShellSort(int array[] , int length){int i,j,temp,gap;int judgeCount = 0, changeCount = 0;//Notice1:設置希爾增量序列初始值 gap = length/2 ,一直循環值gap=1進行最后一次插入排序for(gap = length/2 ; gap >0 ; gap /=2){//Notice2:內層嵌套一個直接插入循環for(i = gap ; i < length ; i++ ){judgeCount++;if(array[i] < array[i - gap]){temp = array[i];for(j = i - gap ; j >= 0 && array[j] > temp ; j -=gap){array[j+gap] = array[j];changeCount++;}array[j+gap] = temp;}}}printf("Judge Count : %d ,Change Count : %d .\n", judgeCount,changeCount); }歸并類排序
歸并類排序:歸并排序遞歸實現與非遞歸實現。
當歸并排序以O(NlogN)最壞情形運行時間運行時,而所使用的比較次數幾乎是最優的。其核心算法Merge的基本操作為:合并兩個已經有序的子列。
遞歸實現
//Notice1:歸并排序的核心,兩個有序子列的歸并 void Merge(int array[] , int tmpArray[] , int l ,int r ,int rEnd ) {//Notice2:根據傳入的參數得出所要歸并的兩個有序子列的總長度length、//左端有序子列起點l、終點lEnd、右端有序子列起點r、終點rEndint length = rEnd - l + 1;int lEnd = r -1;int temp = l;//Notice3:當同時滿足左端指示位置 l <= lEnd、 右端指示位置 r <= rEnd 時,進入while循環//此處while循環判定條件為 <= ,當 = 時,進行該子列最后一個元素的比較while( l <= lEnd && r <= rEnd){//Notice4:此處判斷條件為<=,當兩個指示指針所指的兩個子列中的元素相等時,保持其先后次序if(array[l] <= array[r]) tmpArray[temp++] = array[l++];else tmpArray[temp++] = array[r++];}while( l <= lEnd)tmpArray[temp++] = array[l++];while( r <= rEnd)tmpArray[temp++] = array[r++];for(int i = 0 ; i < length ; i++ , rEnd--){array[rEnd] = tmpArray[rEnd];} }void Merge_Sort(int array[] ,int tmpArray[] , int l ,int rEnd ) {int mid;if( l < rEnd){mid = (l + rEnd)/2;Merge_Sort(array,tmpArray,l,mid);Merge_Sort(array,tmpArray,mid+1,rEnd);Merge(array,tmpArray,l,mid+1,rEnd);} }void MergeSort(int array[] , int length) {int tmpArray[length];Merge_Sort(array,tmpArray,0,length-1);free(tmpArray); }非遞歸實現
//Notice1:歸并排序的核心,合并兩個有序子列 void Merge(int array[] , int tmpArray[] , int l , int r, int rEnd) {int length = rEnd - l + 1;int lEnd = r - 1;int temp = l;while( l <= lEnd && r <= rEnd){if(array[l] < array[r]) tmpArray[temp++] = array[l++];else tmpArray[temp++] = array[r++];}while( l <= lEnd)tmpArray[temp++] = array[l++];while( r <= rEnd)tmpArray[temp++] = array[r++];for(int i = 0 ; i < length ; i++ , rEnd--){array[rEnd] = tmpArray[rEnd];} }//Notice2:對子列長度為gap時的一輪完整歸并 void Merge_Pass(int array[] , int tmpArray[] , int length , int gap) {int i,j;for(i = 0 ; i <= length - gap*2 ; i += gap*2)Merge(array,tmpArray, i , i+gap , i + gap*2 -1);if(i+gap < length)Merge(array,tmpArray,i,i+gap,length-1);elsefor(j = i ; j < length ;j++)tmpArray[j] = array[j]; }//Notice3:當子列長度gap<length時,進行一輪完整歸并,并保證排好序的序列賦值到原數組 void MergeSort(int array[] ,int length) {int gap = 1;int tmpArray[length];while(gap < length){Merge_Pass(array,tmpArray,length,gap);gap *= 2;Merge_Pass(tmpArray,array,length,gap);gap *= 2;}free(tmpArray); }REF
書籍:
數據結構與算法分析、大話數據結構
轉載于:https://www.cnblogs.com/sylvan/p/9383107.html
總結
以上是生活随笔為你收集整理的Algorithm——1.排序.md的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在idea中为类和方法自动生成注释
- 下一篇: python运算学习之Numpy ---