QuickSort 快速排序的分析与实现



/*
  快速排序(QuickSort)


  2013年10月3日
  by --- acton
  算法思想 
         快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
(1)   分治法的基本思想 
         分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
(2)快速排序的基本思想 
         设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为: 
①分解:   
         在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。 
    注意: 
         划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]): 
         R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys 
                                    其中low≤pivotpos≤high。 
②求解:   
          通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。 
③组合:   
         因为当 "求解 "步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言, "组合 "步骤无须做什么,可看作是空操作。

  快速排序的复杂度是O(nlgn),其递归树的表示形式应该为T(n) = 2T(n/2) + O(n) 
  (比较理想的情况是刚好一分为2,然后问题的规模变小),但是也不排除会出现 T(n) = T(n-1) + O(n)也就是一边
  有n-1个元素一边的这种情况,此时的复杂度达到了O(n2)了,蜕化跟InsertSort一样,所以关键是那个划分的元素的选取,
  如果没有选取一个比较恰当的pivotkey的话,可能会造成O(n2)的复杂度,但是快速排序在大多的情况下表现的还是比较的优秀的,
  例如当划分为一边为1/10,另一边为9/10, 即为  T(n) = T((1/10)*n)  + T((9/10)*n)  + O(n)的情况时候,解递归树采用渐进的方法

  可以得到其复杂度近似为O(nlgn),(见算法导论中文版 P151),所以快速排序还是比较优秀的一个排序的算法,而且它是在对元素进行原地的排序,



  快速排序的随机化版本:


  如上已经说过,快速排序的key在于partition,而partition的关键在于对pivotkey的选取,如果没有适当的选取,可能会到最坏的复杂度,
  所以此处采用随机化选取那个pivotkey
  如下伪算法的实现:


  Randomized_Partition(A,p,r){
i = RANDOM(p,r);
Exchange(A[i],A[r]);


  return Partition(A,p,r);
  }
  其他的算法都基本没有改变主要是pivotkey的选取,算法导论中P157中用指示器随机 变量证明了该算法的平均复杂度为O(nlgn)


*/

# include <stdio.h>
# define N  10


void Exchange(int * p, int * q){
	int temp = *p;
	*p = *q ;
	*q = temp;
}


int Partition(int A[], int p , int r){
	int pivot = A[r];				//pivot 应该是随机选取的
	int i = p -1 ;
	
	for (int j = p ; j < r ; j ++){
		if(A[j] <= pivot){
			i ++ ;
			Exchange(&A[i],&A[j]);
		}
	}
	Exchange(&A[i+1],&A[r]);


	return i + 1 ;
}


void QuickSort(int A[] ,int p ,int r){
	if (p < r){
		int q = Partition(A,p,r);
		QuickSort(A,p,q-1);
		QuickSort(A,q+1,r);
	}
}


int main(void){


	int a [N] = {9,2,10,11,2,8,7,4,3};
	QuickSort(a,3,8);


	for (int i = 3 ; i < 9 ; i ++ ){
		printf("%5d ",a[i]);
	}


	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值