在算法回顾(一)中,介绍了冒泡排序,它虽然很容易理解,但是效率却着实的低(O(N^2)), 现在让我们来回顾一下另外一种排序算法,它的效率可就高了许多,大概是O(N*logN),这就是 快速排序。
快速排序的中心思想就是:先从待排序的序列中,选择处于中间位置的关键码作为pivot,然后将剩下的元素进行一个筛选,将码值小于pivot的放到左边,码值大的放到右边。然后,分别对pivot左右两边的序列进行一次相同的筛选操作,依次类推,直到最后分的不能再分为止。这个时候整个序列就排序完成了。
说起来简单,做起来难。真正把上面的思想写成代码还是需要下一番功夫的。一般这种情况,最佳实践就是先写出算法的伪代码,然后再用相应的程序语言完成。
伪代码如下:
quickSort(array, left, right) pivot = findpivot(array,left, right)//选择pivot中轴关键码 partition(array,pivot) //对中轴两边进行筛选,小于pivot的放左边,大于pivot的放右边 quickSort(array, left, pivot -1)//对pivot 左边的序列进行相同的操作 quickSort(array, pivot +1, right)//对pivot 右边的序列进行相同的操作
接下来根据这个伪代码使用c来实现:
void quickSort( int a[], int i, int j ) //quickSort(array, left, right) { int pivot = findpivot(a, i, j); //pivot = findpivot(array,left, right)//选择pivot中轴关键码 partition(a, i, j, pivot); // partition(array,pivot) //对中轴两边进行筛选,小于pivot的放左边,大于pivot的放右边 quickSort(a, i, pivot -1); //quickSort(array, left, pivot -1)//对pivot 左边的序列进行相同的操作 quickSort(a, pivot +1, j); //quickSort(array, pivot +1, right)//对pivot 右边的序列进行相同的操作 } int findpivot( int a[], int i, int j ) { return (i + j)/2; }
对于partition这个步骤有很多不同的实现,这里只介绍一种:
1、设置两个标记,一个是最左,一个是最右
2、从左开始遍历,遇到第一个大于pivot值时停止,
3、然后从右开始遍历,直到遇到第一个小于pivot的关键码为止
4、交换步骤2,3中的两个标记指向的关键码的值
5、重复 2、3、4步 直到 定位右边的标记 小于 定位左边的标记为止
实现代码如下:
void partition(int a[], int l , int r, int pivot) { do{ while (a[++l] < pivot) { //左标记从左往右不断遍历,直到碰到大于pivot的关键码 ; } while (a[--r] > pivot) {//右标记从右往左不断遍历,直到碰到小于pivot的关键码 ; } swap(a[l], a[r]); //交换这个两个关键码的值,使之符合左边小右边大的规律 }while (l<r);// 循环便利结束条件:右边的标记比左边的标记小 }
运行,调试然后修改一些细节,我们就得到下面的完整的代码:
1 int partition(int a[], int l , int r, int pivot) 2 { 3 do{ 4 5 while (a[++l] < pivot) { 6 ; 7 } 8 9 while (a[--r] > pivot) { 10 ; 11 } 12 swap(a[l], a[r]); 13 14 }while (l<r); 15 16 swap(a[l], a[r]); // 纠正上面遍历的最后一次 swap 17 18 return l; 19 20 } 21 22 int findpivot(int a[], int i, int j) 23 { 24 return (i+j)/2; 25 } 26 27 void qsort(int a[], int i, int j) 28 { 29 if (j<=i) { 30 return; //do not sort 0 or 1 item 31 } 32 int pivotindex = findpivot(a,i,j); 33 34 swap(a[pivotindex], a[j]); // move the pivot at end 35 36 int k = partition(a, i-1, j, a[j]); 37 38 swap(a[k], a[j]); 39 40 qsort(a, i, k-1); 41 42 qsort(a, k+1, j); 43 44 }