您的位置:首页 > 其它

关于快速排序

2015-09-05 16:09 337 查看
关于快速排序,有许多版本,均需要掌握:

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

在我写的第二篇文章中,我们已经知道:

“再到后来,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=1,j=n,取数组中第一个元素ki为主元,即key<-ki(赋值)。
II、赋值操作(注,以下“->”,表示的是赋值):
j(找小),从右至左,不断--,直到遇到第一个比key小的元素kj,ki<-kj。
i(找大),从左至右,不断++,直到遇到第一个比key大的元素ki,kj<-ki。
III、按上述方式不断进行,直到i,j碰头,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++实现

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