1.哨兵位置为最终位置
2.partition就是切分过程
3.选择一个哨兵,将一组数划分为全比它小、全比它大的左右两部分,再分别对这两部分继续如此左右划分,直到元素个数为1.整个划分结束时,数组已排好序。
4.至于partition过程,参见上图。
5.图一的划分方式,退出循环后i所指为第一个大于等于vot的元素,j所指为最后一个小于等于vot的元素。因此最后使a[j]与a[lb]交换即可让哨兵归至原位。
伪码:
void quickSort(int a[],int p,int r){
if(p<r){
int q=partition(a,p,r);
quickSort(a,p,q-1);
quickSort(a,q+1,r);
}
}
代码:
import java.util.Scanner;
public class 快排递归 {
static void swap(int a[],int i,int j) {
int tmp = a[i];
a[i]=a[j];
a[j]=tmp;
}
static int partition(int a[],int lb,int ub) {
//以下为图一划分方式
int i=lb,j=ub+1;
int vot=a[i];
while(true) {
while(i<ub&&a[++i]<vot);
while(a[--j]>vot);
if(i<j) swap(a,i,j);
else break;
}
a[lb]=a[j];
a[j]=vot;
return j;
//以下为图二划分方式
/*int i=lb,j=ub;
int vot=a[i];
while(true) {//一旦j==i就终止循环。因为左游标左侧、右游标右侧代表已处理妥当的元素。而左右游标之所指,代表要互相比较的两个元素。相遇时,游标左右已妥,而游标本身进行对比不会改变什么。因此结束。
while(j>i&&a[j]>=vot) j--;
if(j>i) {//加这个条件是筛掉,如,基准元素左侧全是比它小的。下同。
a[i++]=a[j];
}
while(j>i&&a[i]<=vot) i++;
if(j>i) {
a[j--]=a[i];
}
if(!(j>i)) break;
}
a[i]=vot;
return i;*/
}
static void quickSort(int a[],int lb,int ub) {
int q=-1;
if(ub>lb) {
q=partition(a, lb, ub);
quickSort(a, lb, q-1);
quickSort(a, q+1, ub);
}
}
public static void main(String args[]) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int a[]=new int[n];
for(int i=0;i<n;i++) {
a[i]=sc.nextInt();
}
quickSort(a, 0, n-1);
for(int i=0;i<n;i++) {
System.out.println(a[i]);
}
}
}