標籤:最佳化 swa 資料結構 希爾排序 最小值 演算法分析 mina 直接 有序
排序演算法
交換排序類:冒泡排序、快速排序
選擇排序類:簡單選擇排序、堆排序
插入排序類:直接插入排序、希爾排序
冒泡排序
冒泡排序(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;}
簡單選擇排序
簡單選擇排序(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]); } }}
直接插入排序
直接插入排序(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);}
堆排序
堆排序(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 ); }}
快速排序
快速排序(Quick Sort)是在實踐中最快的已知排序演算法,平均已耗用時間是O(N log N)。快速排序之所以快是因為其精鍊的、高度最佳化的內部迴圈。最壞情況的效能為O(N2),如今高度最佳化後的快速排序簡單易懂並且不難證明。
和歸併排序一樣,快速排序也是一種分治的遞迴演算法。
將數組array進行快速排序QuickSort的基本演算法由以下簡單的四步組成:
- 1.如果數組長度為0或者1,則直接返回;
- 2.使用Median3或其他方法擷取樞紐元素pivot;
- 3.劃分子集;
- 4.遞迴調用QuickSort
REF
書籍:
資料結構與演算法分析、大話資料結構
演算法基礎——1.排序