快速排序

来源:互联网 发布:淘宝取店名 编辑:程序博客网 时间:2024/06/06 16:36

快速排序:

基本原理:快速排序也是基于分治模式的。

 

分治过程的三个步骤:

分解:数组A[p...r]被划分成两个(可能空)子数组A[p..q-1]和A[q+1...r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。下标q也在这个划分过程中进行计算。

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

合并:因为两个子数组是就地排序的,将它们的合并不需要操作:整个数组A[p...r]已排序。

 

平均运行时间:O(nlgn),最坏情况运行时间为O(n^2)。

 

以上摘自《算法导论》

 

一个版本代码实现:

#include<stdio.h>#define N 50 int A[N] ;int Partition(/*int *A*/int p,int r) ;void QuickSort(/*int *A*/int p,int r) ;int main(void){int i,n ;freopen("in.txt","r",stdin) ;while(scanf("%d",&n) != EOF){for(i = 0 ; i < n ; ++i){scanf("%d",&A[i]) ;}printf("You had input the List:\n") ; for(i = 0 ; i < n ; ++i){printf("%-3d",A[i]) ;}printf("\n") ;QuickSort(/*A*/0,n-1) ;printf("After Sort:\n") ;for(i = 0 ; i < n ; ++i){printf("%-3d",A[i]) ;}printf("\n\n") ;}return 0 ;}int Partition(/*int *A*/int p,int r) {int x = A[r] ;int i,j,nTemp ;i = p - 1 ;for(j = p ; j < r ; ++j){if(A[j] <= x){i++ ; nTemp = A[i] ;A[i] = A[j] ; A[j] = nTemp ; }}nTemp = A[i+1] ;A[i+1] = A[r] ;A[r] = nTemp ;return i+1 ;}void QuickSort(/*int *A*/int p,int r) {int q = 0 ;if(p < r){q = Partition(p,r) ;QuickSort(p,q-1) ;QuickSort(q+1,r) ;}}


这个版本对于我来说比较好理解,特别是Partition这个函数。它将数组分为4个区间,一个是元素比主元小的区间,一个是元素比主元大的区间,一个是元素未进行与主元比较的区间,一个是主元区间。(《算法导论》有图解,更清晰)

Partition这个函数其实很好用,今天在其它地方看到两个面试题,其中一个大概就是:对一个包含正负数的数组进行处理,处理完毕之后要求全部负数在全部正数左边。时间复杂度要求O(n),空间复杂度O(1)。

思路:其实就是对0的Partition。不过,也有其它方法,之前写过,就不再提了。

另外一个面试题就是包含奇偶数的,也是要进行分开。其实也是一样的道理。

 

 

下面附上另外一个快速排序的版本,自己压根没理解:

void qsort(int lt,int rt){    int i,j,mid,t;    i = lt;    j = rt;    mid = a[ (lt + rt) / 2 ];    do    {        while (a[i] < mid && i<rt) ++i;        while (a[j] > mid && j>lt) --j;        if (i<=j)        {            t = a[i];a[i] = a[j];a[j] = t;            ++i;--j;        }    }while (i<=j);    if (i<rt) qsort(i,rt);    if (j>lt) qsort(lt,j);}