题目详见算法导论7-2习题,在这里我就不再赘述。
本文分为三个部分,第一部分是写我改进算法的思路,第二部分是算法实现,第三部分是程序运行结果。
思路
《算法导论》里介绍的partition没有考虑元素相等的情况,但是就算存在相同元素快排其实也可以适用的,只是相等的元素当作大于key的元素处理了。习题7-2要求经过partition函数之后与数组变为三个部分,最左边的是小于key(就是原算法里的a[r]),中间部分等于key,最右边大于key。联想到原来的partition函数采用一个变量i来记录小于key的元素的个数,我想可不可以也采用一个变量t来记录小于等于key的元素个数,其中i+1到t是等于key的元素。因此,当出现小于或者等于key的元素t加一,i也要加一。然后按照原来的思想exchange(a[t],a[j])。但是又到了解决问题的关键,只是这样交换一次还不能达到我们的目的,我们必须注意到这个现象从p到i是小于key的元素,从i+1到t是等于key的元素,我们经过exchange(a[t+1],a[j])之后a[t+1]是一个小于等于key的元素,若其小于key我们需要exchange(a[t],a[i]),将小于key的元素交换到最左边,这样我们就成功的将数组里元素分为三部分。
算法实现
int *partition(int *a,int p,int r)
{
int key=a[r];
int i=p-1;
int t=p-1;
int j,temp;
for(j=p;j<r;j++)
{
if(a[j]<key) //比key小就放在左边
{
i++;
t++;
temp=a[t];
a[t]=a[j];
a[j]=temp;
if(i<t)
{
temp=a[t]; //与key一样大小的swap
a[t]=a[i];
a[i]=temp;
}
}
else if(a[j]==key)
{
t++;
temp=a[t];
a[t]=a[j];
a[j]=temp;
}
}
temp=a[r]; // i+1到t+1等于key
a[r]=a[t+1];
a[t+1]=temp;
int *po=(int *)malloc(sizeof(int)*2); //存储返回值
*po=i+1;
*(po+1)=t+1;
return po;
}
void quicksort(int *a,int p,int r)
{
int *po;
if(p<r)
{
po=partition(a,p,r);
quicksort(a,p,*po-1);
quicksort(a,*(po+1)+1,r);
}
}