您的位置:首页 > 其它

排序算法(快速排序)

2011-10-05 00:01 190 查看
快速排序是一个分治过程:

对于数组A[p….r]选取A中的一个元素A(q),按照大小将A分成两部分 A[p…q-1] 和 A[q….r]

其中 A[p…q-1] 中所有的元素都小于A(q),而 A[q….r]中所有元素都大于 A(q).

对于划分后的数组依然采用同样的方法分裂。注意分裂后的数组可以为空,如此进行下去直到

分裂后的元素不超过一个,这将所有的小数组合并在一起就是排好序的。

递归算法如下:

quicksort(A,p,r)

if p<r

then q=partition(A,p,r)


quicksort(A,p,q-1)



quicksort(A,q,r)


算法的关键是对数组的分裂,下面用图示显示分裂过程

不妨取选取A的最后一个元素为比较元素A(q)=A[r]

用 p 记录起点,r 记录终点,j 记录当前还未做比较的起点位置,i 记录当前做完比较的分界点,即小数组的最后一个位置

(1) 比较A[j]和A[r]的大小,

如果A[j]<=A[r] 则交换A[j]和A[i+1],j++,i++ (A[j]在小数组位置)

否则,j++, (A[j]在大数组位置)

(2) 当 j = r 时,说明所有点都以比较,此时交换 A[i+1] 和 A[r] ,返回 i +1 即可





如果数组本身已经按照从小到大排好了序,可以想见其算法复杂度很高,这是最坏的情况,

这相当于每两个元素之间都要相比较,则复杂度是

\sum_{ i=1 }^n ( n-i ) = n(n-1)/2 = O(n^2) 很大 (堆排序是 O(nlogn))

最好的情况是每次都二分,算法复杂度是

T(n) = 2T(n/2) + O(n)

不妨令 n=2^k, O(n)=Cn, C为常数

则T(n) = 2T(2^{k-1})+Cn = 2( 2T(2^{k-2})+Cn/2)+Cn = 2^2T(2^{k-2})+2Cn

=………=2^k T(1)+Ckn = nT(1)+Cnlogn = O(nlogn) .

算法的复杂度当然是每次划分的程度有关,希望大小子树比例接近与1:1.

下面使用随机化的快速排序算法,其期望复杂度是 O(nlogn) 还是不错的:

// quicksort.cpp : 定义控制台应用程序的入口点。
//
//此程序为快速排序算法和随机化版本,原理是每次将向量分成大小两堆
//2011/3/25 肖成
#include <vector>
#include <iostream>
using namespace std;
#define N 20

template<class T>
int partition(vector<T>& A, int p, int r);

template<class T>
void quicksort(vector<T>& A, int p, int r);

template<class T>
int random_partition(vector<T>& A, int p, int r);

template<class T>
void random_quicksort(vector<T>& A, int p, int r);

int main()
{
double a[]={2,4,3,5,8,7,9,0,11,15,23,32,12,16.4,32,23,2.8,1,42,6,8};
cout<<"The original vector is :"<<endl;
for(int i=0;i<N+1;i++)
cout<<a[i]<<"  ";
cout<<endl;
cout<<"-----------------------------------------------------------------------------------"<<endl;
vector<double> vec(a,a+N+1);
vector<double>::iterator iter;

cout<<"quicksort"<<endl;
cout<<"-----------------------------------------------------------------------------------"<<endl;
quicksort(vec,0,N);
for(iter=vec.begin();iter!=vec.end();iter++)
cout<<*iter<<"  ";
cout<<endl;

cout<<"random_quicksort"<<endl;
cout<<"-----------------------------------------------------------------------------------"<<endl;
vector<double> vecrand(a,a+N+1);
random_quicksort(vecrand,0,N);
for(iter=vecrand.begin();iter!=vecrand.end();iter++)
cout<<*iter<<"  ";
cout<<endl;
return 0;
}

template<class T>
int partition(vector<T>& A, int p, int r)
{
T x=A[r];
int i=p-1;
for(int j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i=i+1;
T temp=A[i];
A[i]=A[j];
A[j]=temp;
}
}
A[r]=A[i+1];
A[i+1]=x;
return i+1;
}

template<class T>
void quicksort(vector<T>& A, int p, int r)
{
if(p<r)
{
int q=partition(A,p,r);
quicksort(A,p,q-1);
quicksort(A,q+1,r);
}
}

template<class T>
int random_partition(vector<T>& A, int p, int r)
{
int i=rand()%(r-p)+p;
T temp=A[r];
A[r]=A[i];
A[i]=temp;
return partition(A,p,r);
}

template<class T>
void random_quicksort(vector<T>& A, int p, int r)
{
if(p<r)
{
int q=random_partition(A,p,r);
random_quicksort(A,p,q-1);
random_quicksort(A,q+1,r);
}
}

其运行结果如下



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: