快速排序的一种写法

一、快速排序的基本特性

时间复杂度: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章,快速排序。 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值