说到排序算法,应该算是家喻户晓,人人皆知的大路货了。可是每每这些为人所熟知的东西中,也存在一些能够使人琢磨的细节。算法
这不,某天深夜,无所事事,大概是太寂寞,在思念了一番妹子之后,脑子里忽然闪过了快速排序,遂在脑子中模拟了一遍快速排序的运行过程,之前只是死记硬背代码,没有去探究其运做的流程,因而在一些细节处陷入了沉思和迷惑,致使脑回路短路,当场打开斗鱼看了会球。网络
首先你们都知道,快排主要有两部分,分段(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上发文章,也是为了巩固和牢记本身这么多天琢磨的东西。若是有什么错误和不足,也请各位看客多多指正和补充。