交換排序是指在排序過程當中,經過待排序記錄序列中元素間關鍵字的比較,將數據元素進行交換來達到排序目的的方法,主要包括冒泡排序和快速排序。git
源碼:https://github.com/fangyz/myDataStructuregithub
/* 冒泡排序的基本思想是對全部相鄰記錄的關鍵字進行比較,若是a[j]>a[j+1]則將其交換,最終達到有序化。其處理步驟以下: (1)首先將整個待排序的記錄分爲有序區和無序區,初始狀態有序區爲空無序區則爲整個待排序的記錄。 (2)對無序區從前日後依次將相鄰記錄的關鍵字進行比較,若逆序則進行交換,從而使得較大的數據元素右移,這樣最終造成有序序列。 經過上面的步驟能夠發現,每一次冒泡排序都將無序區中最大的數據元素移到有序區的最右邊。而且,對於含n個數據元素的數據序列,最多須要通過n-1趟冒泡排序。 */ void BubbleSort(int* a,int length) { if (a == NULL || length <= 0) return; int i, j,temp; for (i = length - 1; i > 0; i--){ for (j = 0; j <i; j++){ if (a[j]>a[j + 1]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } //若是一次循環中,沒有進行數據交換,那麼就說明序列已經有序。 void BetterBubbleSort(int* a, int length){ if (a == NULL || length <= 0) return; int i, j, temp; bool isChanged=false; for (i = length - 1; i > 0; i--){ isChanged = false; for (j = 0; j <i; j++){ if (a[j]>a[j + 1]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; isChanged = true; } } if (isChanged == false) break; } } //更好的冒泡排序 void BestBubbleSort(int *a, int length) { int i, j; int temp; bool isChange; int lastMove; if (a == NULL || length <= 0) return; for (i = length - 1; i>0; i--) { isChange = false; for (j = 0; j<i; j++) //一次執行將最大的數交換到最後面 { if (a[j + 1]<a[j]) { temp = a[j + 1]; a[j + 1] = a[j]; a[j] = temp; isChange = true; //優化點1:若是一次循環中沒有數進行交換那說明已經有序了 lastMove = j; //優化點2:裏面的for執行完畢後, 說明j到i之間的數據已經有序了,j之前的數據可能還不是有序的。 } } if (isChange == false) break; i = lastMove + 1;
} }
冒泡排序是一種穩定的排序方法,由於只有在大於後一個數的狀況下才進行交換。冒泡排序最好狀況比較次數爲n-1,移動次數僅爲0,此時數據元素自己就是有序序列。最壞狀況下比較次數爲n*(n-1)/2,移動次數爲3n(n-1)/2,平均時間複雜度爲O(n^2)。接下來是快速排序。數組
/* 快速排序,能夠看到它的時間複雜度主要集中在外面的while循環,這個循環的做用是進行比較找到一個位置s將數組分爲0~s和s~length,也就是說快速排序的時間複雜度集中在劃分區域上。 在劃分區域時,首先就算劃分了區域,但仍是要對這一整個數組進行比較,比較的次數是一個n階函數,接下來重點就是劃分的次數了。 最好狀況下若是每次都是劃分的中間的區域,那麼劃分次數爲lbn,最壞狀況下若是每次劃分有一個區域是空的,那將會劃分n-1次,故時間複雜度最壞O(n^2),最好是O(lbn)。 至於爲何平均時間複雜度爲O(nlbn)課本上寫了一大堆計算公式然而暫時並無看懂。。。。 */ void QuickSort(int *a, int start, int end) { if (a == NULL || start < 0 || (start>=end)) return; int s = start, e = end - 1; int index; int value = a[s]; while (s < e){ //必定要注意這個地方加=,由於若是不加的話,就是死循環了。 //這個地方還有一點要注意,那就是要加上s<e,由於條件是大於或等於,那麼這時有可能e會小於s。 while (a[e]>=value&&s<e) e--; //如今執行到這個地方說明a[e]<value了,因此要讓a[s]=a[e],a[e]=value,可是這裏只對a[s]進行了賦值, //緣由是在循環中,讓a[s]=a[e]後,接下來的while循環可以繼續執行,當遇到a[s]>value時,此時進行替換的是a[e],即將大的數放到e這個地方。 //這樣能夠發現讓a[s]=a[e]後就可讓s向前增長,當s增長到a[s]>value時便讓a[e]=a[s],這樣下一次while循環中a[e]便大於value了額,e就能夠向後減小了。 a[s] =a[e]; while (a[s] <= value&&s<e) s++; a[e] = a[s]; //咱們還能夠發現每次執行到這個地方的時候,數組中有2個重複值, //那就是a[e]==a[s]>value,若是不知足s<e跳出循環那就要讓a[s]=value。 } a[s] = value; if (s < end - 1) QuickSort(a, s + 1, end); if (s>start + 1) QuickSort(a, start, s); }