快速排序对给定数组中的元素 进行重新排列,以得到一个快速排序的分区,在一 个分区中,所有在s下标之前的元素都小于等于A[s],所有在s下标之后的元素都大于等于A[s],即A[s]已经位于它在有序数组中的最终 位置。
1.首先选择一个元素为中轴,一般选择为第一个元素, A[l]
2.建立分区:分别扫描与中轴比较,一次从左到右(用i表示)直到遇到第一个大于中轴的元素,另一次从右到左(用j表示)直到遇到第一个小于等于中轴的元素
3.两次扫描全部停止会发生3种不同的情况
1)扫描指针i,j不相交,即i<j,交换A[i]和A[j],再分别对i+1,j-1,然后继续进行扫描
2)扫描指针相交, 即i>j,把中轴和A[j]交换以后,得到该数组的一个分区
j | i | |||
p | 全部p | p | p | 全部p |
3)扫描指针指向同一个元素,也就是i=j,被指向的元素一定等于p,建立该数组的一个分区,分裂点的 位置S=i=j。
i=j | ||||
p | 全部p | =p | 全部p |
合并后两种情况,只要ij,就交换中轴和A[j]的位置。
注意:在这种形式下,下标i可能会超过子数组的边界
如果所有的分裂点位于相应子数组的中点,就是最优情况,键值的比较次数:
在最差情况下,所有的分裂点都趋于极端:两个子数组有一个为空,而另一个子数组仅仅被分区数组少一
个元素,这会在已 排好序的情况下出现,键值的比较次数:
平均情况下,当n>1时,
因此在平均情况下,仅比最优情况下多执行38%的比较操作,其最内 层循环效率非常高,使得在处理随机排列的数组时,速度要比合并排序快。
void QuickSort(int a[],int l,int r)
{
if (l<r)
{
int i=l,j=r,key=a[l];
while(i<j)
{
while(i<j && a[j]>=key)
j--;
if (i<j)
{
a[i++] = a[j];
}
while(i<j && a[i]<key)
i++;
if (i<j)
{
a[j--] = a[i];
}
}
a[i]=key;
QuickSort(a,l,i-1);
QuickSort(a,i+1,r);
}
return;
}