以某个记录(元素)为界(该记录称为支点或枢轴),将待排序列分成两部分:
①一部分: 所有记录的关键字大于等于支点记录的关键字
②另一部分: 所有记录的关键字小于支点记录的关键字
算法描述:
1、任取待排序记录序列中的某个记录(例如取第一个记录)作为基准(枢),按照该记录的关键字大小,将整个记录序列划分为左右两个子序列
2、左侧子序列中所有记录的关键字都小于或等于基准记录的关键字
3、右侧子序列中所有记录的关键字都大于基准记录的关键字
4、基准记录则排在这两个子序列中间(这也是该记录最终应安放的位置)。
5、然后分别对这两个子序列重复施行上述方法,直到所有的记录都排在相应位置上为止。
public class SortMethods {
/*输出数组中的元素*/
private static void print(int[] a) {
for(int num: a){
System.out.print(num+"\t");
}
System.out.println();
}
private static void swap(int[] a, int i, int j) {
int temp;
temp =a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int a[] = {0,21,25,49,25,16,15,8,-2,0,-9,67,34,5,12,40};
shellSort(a);
print(a);
}
private static void quickSort(int[] a, int p, int r) {
if(p<r){
//把数组划分成两个子数组和一个元素(枢轴):
//用枢轴a[q]把整数数组划分成 ==> a[p,q-1] , a[q] , a[q+1,r]
int q = partition(a,p,r); //a[q]
quickSort(a,p,q-1);//排左边的子数组a[p,q-1]
quickSort(a,q+1,r);//排右边的子数组a[q+1,r]
}
}
private static int partition(int[] a, int p, int r) {
//优化:采用随机选择策略确定枢轴----随机选取数组当中的一个元素,和第一个元素进行交换。之后,以第一个元素作为枢轴进行划分
int rand = (int)(Math.random()*(r-p));//rand为区间内的随机序号(第几个)//p=10000, r=15000
swap(a,p,p+rand);
int i=p;//第一个元素定为枢轴
int j=r+1;
int x=a[p];
while(true){
while(a[++i]<x && i<r);//定位指针i,找比x大的元素 <--为的是找要交换到右边的"非法"元素
while(a[--j]>x);//定位指针j <--为的是找要交换到左边的"非法"元素
if(i>=j){
break;
}
swap(a,i,j);
}
swap(a,p,j);//枢轴a[p]要换到中间位置
return j;
}
}