快速排序的一种写法

来源:互联网 发布:java集合类有哪些 编辑:程序博客网 时间:2024/05/20 23:06

一、快速排序的基本特性

时间复杂度:O(n*lgn)

最坏:O(n^2)

空间复杂度:O(n*lgn)不稳定。

快速排序时基于分治模式处理的,对一个典型子数组A[p...r]排序的分治过程为三个步骤:

1.分解:A[p..r]被划分为两个(可能空)的子数组A[p ..q-1]和A[q+1 ..r],使得A[p ..q-1] <= A[q] <= A[q+1 ..r],下标q在这个划分过程中进行计算。

2.解决:通过递归调用快速排序,对子数组A[p ..q-1]和A[q+1 ..r]排序。

3.合并:因为两个子数组是就地排序的,讲它们的合并不需要操作。

二、快速排序算法的描述

算法导论,第7章P85

PARTITION(A, p, r)  x ← A[r]         //以最后一个元素,A[r]为主元  i ← p - 1  for j ← p to r - 1    //注,j从p指向的是r-1,不是r。       do if A[j] ≤ x             then i ← i + 1                  exchange A[i] <-> A[j]  exchange A[i + 1] <-> A[r]    //最后,交换主元  return i + 1

    然后,对整个数组进行递归排序:

QUICKSORT(A, p, r) if p < r    then q ← PARTITION(A, p, r)   //关键         QUICKSORT(A, p, q - 1)         QUICKSORT(A, q + 1, r)

根据上述伪代码,写出以下的c/c++程序:
首先是,PARTITION过程:

int partition(int data[],int lo,int hi) {   int key=data[hi];  //以最后一个元素,data[hi]为主元 int i=lo-1;   for(int j=lo;j<hi;j++)   ///注,j从p指向的是r-1,不是r。     {        if(data[j]<=key)         {            i=i+1;            swap(&data[i],&data[j]);         }      }   swap(&data[i+1],&data[hi]);   //不能改为swap(&data[i+1],&key)   return i+1;}

补充说明:举个例子,如下为第一趟排序(4步):

   a:3   8   7   1   2   5   6   4   //以最后一个元素,data[hi]为主元

   b:3   1   7   8   2   5   6   4

   c:3   1   2   8   7   5   6   4

   d:3   1   2   4   7   5   6   8    //最后,swap(&data[i+1],&data[hi])

  而其中swap函数的编写,是足够简单的: 

void swap(int *a,int *b){   int temp=*a;   *a=*b;   *b=temp;}

    然后是,调用partition,对整个数组进行递归排序:

void QuickSort(int data[], int lo, int hi){    if (lo<hi)    {        int k = partition(data, lo, hi);        QuickSort(data, lo, k-1);        QuickSort(data, k+1, hi);    }} 

摘录算法导论上的例子

 2   8   7   1   3   5   6   4(主元)


    当然,快速排序要很多实现方法,比如:算法导论上的单向扫描版本、双向扫描版(Hoare版本及其变形)、随机化版本、三数取中分割法以及非递归实现。这里不作介绍了,因为July博主总结的非常完善了。见参考。


参考:1.http://blog.csdn.net/v_JULY_v/article/details/6262915

            2.http://blog.csdn.net/v_JULY_v/article/details/6116297

            3.算法导论第7章,快速排序。