算法回顾(二):快速排序

 

算法回顾(一)中,介绍了冒泡排序,它虽然很容易理解,但是效率却着实的低(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 }

 

posted on 2013-08-06 21:45  隔热  阅读(312)  评论(0编辑  收藏  举报