快速排序采取的是分治的策略。
1、分区:在区间内选取一个基数X(一般是区间的第一个数),将小于X的数放在X的左边,将大于X的数放在X的右边,这样就将区间分成了左右两个子区间
2、分治:对左右区间重复步骤1,直到区间内只剩下一个数(只有一个数就不用再进行步骤1)
经过以上分析,可以知道快速排序的要点在于分区。分区采用的是一种挖坑+填坑的策略。
挖坑+填坑这两个词实在是太抽象,用一个例子来演示这个过程
现在对数组a={72,6,57,88,60,42,83,73,48,85}进行排序
1、取区间的第一个数a[0]为基数X,将a[0]挖出形成第一个坑,此时i=0,j=9
2、从右边开始在(i,j]中找一个比X小的数,a[8]=48符合要求,将a[8]挖出填到上一个坑a[0]处,此时i=1,j=8
3、从左边开始在[i,j)中找一个比X大的数,a[3]=88符合要求,将a[3挖出填到上一个坑a[8]处,此时i=3,j=7
4.、重复步骤2,3直到i==j,令a[i]=a[j]=X
72 6 57 88 60 42 83 7348 85
48 6 57 88 60 42 83 73 48 85
48 6 57 88 60 42 83 73
88 85
48 6 57 42 60 42 83 73 88 85
48 6 57 42 60 72 83 73 88 85
分区总结:
1、对区间[l,r]进行分区,取a[l]=X,i=l,j=r
2、从右开始在区间(i,j]中找一个比X小的数赋值给a[i],假如a[k]符合要求,i=i+1,j=k
3、从左开始在区间[i,j)中找一个比X大的数赋值给a[j],假如a[k]符合要求,j=j-1,i=k
4、重复步骤2,3直到i==j,令a[i]=a[j]=X
分区代码模板:
static int partition(int l,int r)
{
int i=l;int j=r;int x=a[i];
while(true)
{
while(i<j && a[j]>=x) j--;//a[j]<x或者i==j时退出
if(i<j)
{
a[i]=a[j];//把i处的坑填好,在j处挖坑
i=i+1;
}else
{
break;
}
while(i<j && a[i]<=x) i++;
if(i<j)
{
a[j]=a[i];//把j出的坑填好,在i处挖坑
j=j-1;
}else
{
break;
}
}
a[i]=x;
return i;
}
分治代码模板
static void quickSort(int l,int r)
{
if(l>=r){
return;
}
int q=partition(l, r);
quickSort(l, q-1);
quickSort(q+1, r);
}