您的位置:首页 > 其它

快速排序的三种实现方法体会

2014-04-13 21:35 288 查看
       快速排序有三种实现方法,网上也有不少人总结出来,但是其中或多或少都有些错误。在这里只是说一下我自己的心得和体会。

       三种快速排序算法的区别其实就是分割操作的区别。说它有三种快速排序,也只是说它有三种分割操作而已。

分割操作:

将一个数组分为两部分,左半部分的数值都小于等于某一个数p,右半部分的数值都大于等于p。

第一种快速排序:大多数教科书里教给我们的方法,在前一文中已经说明。这里总结一下:

思想:

分割操作:选取数组中的第一个元素作为中位数p,此数将数组分为A[......., p ,........].数组的左半部分的数值都小于或等于p,数组的右半部分都大于或等于p。

然后对数组左右部分再进行递归的分割操作,直到整个数组完全有序为止。

分割操作步骤:

1. 选取A[low]作为中位数p,

2. 从数组的最右端往前找小于等于p的数:    A[j]<=p;  A[low]=A[j];

3. 再从数组的最左端往后找大小等于p的数:A[i]>=p;  A[j]=A[i];

4. 再从数组的第j位置往前找小于等于p的数:A[j]<=p;  A[i]=A[j]

5. 重复操作3,4.直到i==j为止。然后将A[i]=p;

分割结束。

例子:

{41, 24, 76, 11, 45, 64, 21, 69, 19, 11}

p=41;

{11, 24, 76, 11, 45, 64, 21, 69, 19, 11}

{11, 24, 76, 11, 45, 64, 21, 69, 19,76}

{11, 24,19, 11, 45, 64, 21, 69, 19, 76}

{11, 24, 19, 11, 45, 64, 21, 69, 45, 76}

{11, 24, 19, 11,21, 64, 21, 69, 45, 76}

{11, 24, 19, 11, 21, 64,64, 69, 45, 76}

{11, 24, 19, 11, 21, 41, 64, 69, 45, 76}

{11, 24, 19, 11, 21}{ 41}{ 64, 69, 45, 76}

分割结束。

int Partion(int A[],int low,int high){
int temp=A[low];
while(low<high){
while(low<high&&temp<=A[high])
high--;
A[low]=A[high];
while(low<high&&temp>=A[low])
low++;
A[high]=A[low];
}
A[high]=temp;
return high;
}
void QuickSort(int A[],int low,int high){
if(low<high){
int p=Partion(A,low,high);
QuickSort(A,low,p-1);
QuickSort(A,p+1,high);
}
}


第二种快速排序:
思想:
分割操作:选取p=A[(low+high)/2],作为中位数。将数组分割成A[........,...........]. 左半部分小于等于p,右半部分大于等于p,此时p的位置可能在左半部分中,也可能在右半部分中。
分别对数组的左半部分和右半部分递归进行分割操作,直至数组全部有序。
分割操作步骤:
1. 选取p=A[(low+high)/2]作为中位数
2. 从low往后找到一个大于p的数A[i],从high往前找到一个小于p的数A[j],swap(A[i],A[j]);
3. 直到low>=high为止,分割结束。
例子:
{41, 24, 76, 11, 45, 64, 21, 69, 19, 11}
p=45;
{41, 24, 76,11, 45, 64, 21, 69, 19,
11}

{41, 24, 11,11, 45, 64, 21, 69, 19,
76}

{41, 24, 11, 11,45, 64, 21, 69,
19
, 76}

{41, 24, 11, 11, 19,64, 21, 69,
45
, 76}

{41, 24, 11, 11,19,64, 21, 69, 45, 76}

{41, 24, 11, 11,19,21, 64, 69, 45, 76}

{41, 24, 11, 11,19,21} {
64
, 69, 45, 76}

分割结束。

 int Partion(int A[], int low, int high)
{
int middle=A[(low+high)/2];//注意这里不能写成middle=(low+high)/2;下面用A[middle].这样是错的!
//因为low和high值一直在变,所以A[middle]的值也一直在变。
while(1){
while(middle>A[low])low++;
while(middle<A[high])high--;
if(high<=low)
break;
int temp=A[high];
A[high]=A[low];
A[low]=temp;
high--;//如果没有这一步,则如果数组中有两相同的数,该程序会进入无限循环。
low++;
}
return high;//注意这里不能是renturn low;否则无线循环
}
void QuickSort2(int A[],int low,int high){
if(low<high){
int p=Partion(A,low,high);
QuickSort2(A,low,p);
QuickSort2(A,p+1,high);
}
}
第三种排序:

思想和第一种一样。不同就是分割方法。

分割思想:

P=A[high];作为中位数。

处理中的数组:

{{小于p},{大于p},{未处理},{p}}

处理结束后的数组:

{{小于p},{大于p},{p}}

{{小于p},{p},{大于p}}

I作为小于p分数组的最后一位下标,初试为-1;

J作为大于p的分数组的最后一位下标,也是处理中当前处理的元素下标。初始为0;末值为high。

遍历数组j=0;j<high; j++; if(A[j]<p) swap(A[++i],A[j]);

例子:

{41, 24, 76, 11, 45, 64, 21, 69, 19, 34}

P=34;

{41, 24, 76,11, 45, 64, 21, 69, 19, 34}

{24, 41, 76, 11, 45, 64, 21, 69, 19, 34}

{24, 41, 76, 11, 45, 64, 21, 69, 19,34}

{24, 11, 76, 41, 45, 64, 21, 69, 19, 34}

{24, 11, 76, 41, 45, 64, 21,69, 19, 34}

{24, 11, 21, 41, 45, 64, 76, 69, 19, 34}

{24, 11, 21, 41, 45, 64, 76, 69, 19,34}

{24, 11, 21, 19, 45, 64, 76, 69, 41, 34}

{24, 11, 21, 19, 45, 64, 76, 69, 41, 34}

{24, 11, 21, 19}  34 {64, 76, 69, 41,45}

分割结束。

int Partion(int A[], int low, int high){
int i=low-1;
int p=A[high];
for(int j=low;j<=high;j++){
if(A[j]<=p){
int temp=A[++i];
A[i]=A[j];
A[j]=temp;
}
}
return i;
}
void QuickSort3(int A[], int low, int high){
if(low<high){
int p=Partion(A,low,high);
QuickSort3(A,low,p-1);
QuickSort3(A,p+1,high);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: