快速排序的多种实现比较

快速排序是基于分治模式处理的:对一个典型子数组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]2.解决:通过递归调用快速排序,对子数组A[p ..q-1]和A[q+1 ..r]排序。3.合并。
其中分解的方法有多种,很容易引起混淆,下面逐一介绍。
1. Lomuto从左至右单向扫描版:参见编程珠玑
int partition1(int A[], int p, int r)
{
	t = A[p];		// 首元素为枢纽
	int m = p;
	for(i = p+1; i<=r; i++)
        {     /*   invariant: A[p+1...m] < A[p] && A[m+1...i-1]>=A[p]  */
		if( A[i] < t)
			swap(A[++m], i)
         }
        swap(A[p],A[m]);      //这次交换不可少
	return m;              	
}
2. Lomuto从右至左单向扫描版:参见编程珠玑
int partition2(int A[], int p, int r)
{
	t = A[p]; 		// 首元素为枢纽
	int m = r+1;
	for(i = r; i>=p; i--)
        {     /*   invariant: A[m...r] >= A[p] && A[m-1...i]<A[p]  */
		if( A[i] >= t)
			swap(A[--m], i)
         }
        // swap(A[p],A[m]); 	//这次交换已经包含在for循环内
	return m;              	
}
3. Lomuto从左至右单向扫描版:参见算法导论
int partition3(int A[], int p, int r)
{
	t = A[r]; 		// 尾元素为枢纽
	int m = p-1;
	for(i = p; i<r; i++)
        {     
		if( A[i] <= t)
			swap(A[++m], i)
         }
        swap(A[r],A[m+1]); 	//这次交换不可少
	return m+1;              	
}

上述三个算法的缺点是:当A数组所有元素相同时,n-1次划分中每次

划分都需要O(n)时间去掉一个元素,时间复杂度O(n*n)。

4. Hoare双向扫描版:参见博客<结构之法>

int partition4(int A[],int p,int r)  //双向扫描  
{  
  int key=A[p];  // 首元素为枢纽
  int i=p-1;  
  int j=r+1;  
  for(;;)  
  {  
     do{  
          j--;  
      }while(A[j]>key);  
  
     do{  
         i++;  
      }while(A[i]<key);  
  
     if(i<j)  
     {  
         swap(A[i],A[j]);  
     }  
     else  
     {   
        return j;  //注意这里的返回值是j。
      }  
   }  
}  

5. Hoare变种:参见严蔚敏数据结构
int partition5(int A[],int p,int r)  //双向扫描。
{
 int key=A[p];   //以第一个元素为主元
 int i=p;
 int j=r;
 while(i<j)
 {
  	while(key<=A[h] && i<j) 
   		j--;
  	A[i]=A[j];
  	while(A[i]<=key && i<j) 
   		i++;
  	A[j]=A[i];
 }
 A[i]=key;  
 return i;    //注意这里返回的是i
} 

6. STL qsort 算法:参见侯捷STL源码剖析

int partition6(int A[],int p,int r,int key) //双向扫描。
{
 //这里的key可以是数组中任意一元素的值,但通常是首、尾、中间元素的中位数的值。
 //这里的r其实是数组最后元素的下一个元素,符合STL左闭右开的假定
 while(true)
 {
  	while(A[p]<key)   ++p;
  	--r;
  	while(key<A[r])   --r;
        if( !(p<r) )  return p; //注意这里返回的是p
	swap(A[p],A[r]);
	++r;
 }   
} 
其实我感觉小于号改成小于等于号也行,可能是STL出于泛化的考虑,数据有可能不支持小于等于号。
以上是在看书和看博客过程中的一些思考,可能有些错误,仅记下来待以后看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值