关于快速排序

关于快速排序,有许多版本,均需要掌握:

算法导论中的版本(选取最后一位为主元)

在我写的第二篇文章中,我们已经知道:
“再到后来,N.Lomuto又提出了一种新的版本,此版本….,即优化了PARTITION程序,它现在写在了 算法导论 一书上”:

快速排序算法的关键是PARTITION过程,它对A[p..r]进行就地重排:

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

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

QUICKSORT(A, p, r)
1 if p < r
2    then q ← PARTITION(A, p, r)   //关键
3         QUICKSORT(A, p, q - 1)
4         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])

算法导论的扩展(选取第一位为主元)

void quickSort(int p, int q)   
{   
 if(p < q)   
 {   
  int x = a[p];    //以第一个元素为主元
  int i = p;   
  for(int j = p+1; j < q; j++)   
  {   
   if(a[j] < x)   
   {   
    i++;   
    int temp = a[i];   
    a[i] = a[j];   
    a[j] = temp;   
   }   
  }   
  int temp = a[p];   
  a[p] = a[i];   
  a[i] = temp;   
  quickSort(p, i);   
  quickSort(i+1, q);   
 }   
}  

前后指针法(选取第一位为主元):

在上面,我们已经知道,Hoare的快速排序版本可以通过前后俩个指针,分别指向首尾,分别比较而进行排序。
下面,分析一下此版本,或其它变种问题:

      I、 俩个指针,i指向序列的首部,j指着尾部,即i=1j=n,取数组中第一个元素ki为主元,即key<-ki(赋值)。
       II、赋值操作(注,以下“->”,表示的是赋值):
       j(找小),从右至左,不断--,直到遇到第一个比key小的元素kj,ki<-kj。
       i(找大),从左至右,不断++,直到遇到第一个比key大的元素ki,kj<-ki。
       III、按上述方式不断进行,直到ij碰头,ki=key,第一趟排序完成接下来重复II步骤,递归进行。

这里写图片描述

所以,整趟下来,便是这样:

      3   8   7   1   2   5   6   4
      2   8   7   1   3   5   6   4
      2   3   7   1   8   5   6   4
      2   1   7   3   8   5   6   4
      2   1   3   7   8   5   6   4
      2   1   3   7   8   5   6   4

也能够实现同样地效果;

本文参考了
十二之再续:快速排序算法之所有版本的c/c++实现
快速排序算法的深入分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值