說到排序算法,應該算是家喻戶曉,人人皆知的大路貨了。可是每每這些爲人所熟知的東西中,也存在一些能夠使人琢磨的細節。算法
這不,某天深夜,無所事事,大概是太寂寞,在思念了一番妹子之後,腦子裏忽然閃過了快速排序,遂在腦子中模擬了一遍快速排序的運行過程,之前只是死記硬背代碼,沒有去探究其運做的流程,因而在一些細節處陷入了沉思和迷惑,致使腦回路短路,當場打開鬥魚看了會球。網絡
首先你們都知道,快排主要有兩部分,分段(Partition)和遞歸(Recursive)。分段既將一組數據相對一個參考值分爲兩段,左段比參考值小,右端比參考值大,而後再遞歸對這兩段進行分段。那麼快排的關鍵部分天然就是這個分段算法,有了分段算法,加上遞歸,一個快排算法就寫好了。函數
固然別小看了這個分段算法,是須要好好琢磨一番的。主要是一些臨界值和極端狀況的考慮,個人迷惑即是於此。因而查找了一些書籍和網絡資源,加上本身的思路,總結了四種不一樣的分段算法。細節控能夠來好好感覺一下。spa
之因此叫填坑法,是其運做過程就像填坑同樣。並且一點都不坑,代碼形式很是好理解。指針
代碼以下:code
int partition(int a[], int start, int end){ int p = a[start]; while(start < end){ while(a[end] >= p && start < end) end--; a[start] = a[end]; while(a[start] < p && start < end) start++; a[end] = a[start]; } a[start] = p; return start; } void qs(int a[], int start, int end){ if(start >= end){ return; } int mid = partition(a, start, end); qs(a, start, mid-1); qs(a, mid+1, end); }
交換法,顧名思義就是要對兩邊的元素進行交換,再代碼形式中用到swap函數。其流程以下:blog
代碼以下:排序
void swap(int* a, int* b){ int temp = *a; *a = *b; *b = temp; } int partition(int a[], int start, int end){ int pivot = a[start]; int p = start+1; int q = end; while(p <= q){ while(a[p] < pivot && p <= q) p++; while(a[q] >= pivot && p <= q) q--; if(p < q){ swap(&a[p], &a[q]); } } swap(&a[start], &a[q]); return q; } void qs(int a[], int start, int end){ if(start >= end){ return; } int mid = partition(a, start, end); qs(a, start, mid-1); qs(a, mid+1, end); }
能夠看出這個方法和第二個方法有什麼不一樣的地方,爲何要選第二個元素爲start遞歸
上面兩種方法是維護了一個start,一個end指針,逐步向中間趨近的過程。而順序遍歷用一次遍歷完成對數據的分段。圖片
代碼以下:
void swap(int* a, int* b){ int temp = *a; *a = *b; *b = temp; } int partition(int a[], int start, int end){ int pivot = a[end]; int storeIndex = start; for(int i = start; i < end; i++){ if(a[i] < pivot){ swap(&a[storeIndex], &a[i]); storeIndex++; } } swap(&a[storeIndex], &a[end]); return storeIndex; } void qs(int a[], int start, int end){ if(start >= end){ return; } int mid = partition(a, start, end); qs(a, start, mid-1); qs(a, mid+1, end); }
這個方法和以前的交換法的思路相同,可是它不返回mid值,因此索性稱之爲另類交換法吧。運做的流程就不作解釋,直接上代碼,各位客官姑且一看。
void qs(int a[], int start, int end){ if(start >= end){ return; } int pivot = a[start]; int p = start; int q = end; while(1){ while(a[p] < pivot) p++; while(a[q] > pivot) q--; if(p >= q){ break; } swap(&a[p], &a[q]); p++; q--; } qs(a, start, p-1); qs(a, q+1, end); }
這四種算法用了四種不一樣的解決問題的思路,雖然都是細節上的不一樣,可是細細去想一下也能領會其中到奧妙。第一次在sf上發文章,也是爲了鞏固和牢記本身這麼多天琢磨的東西。若是有什麼錯誤和不足,也請各位看客多多指正和補充。