算法思路:以数组第一个数为基数x,然后分别从数组两端开始“探测”。如果按从小到大排序,先从右往左找一个比x小的数此为左哨兵,再从左往右找一个大于x的数此为右哨兵,然后交换他们。之后继续此操作直到左和右哨兵下标相等。当下标相等时就与基数x交换位置,这样基数就到中间的位置了。后面就利用二分法的方式,以中间刚换好的基数为准,分成左和右两个数组,继续按上面的方式执行。
package com.jushi.util;
import java.util.Random;
public class Test {
public static void main(String[] args) {
int []a = new int[10];
//生成随机数组
Random random = new Random();
System.out.print("交换前数组:");
for (int i = 0;i < a.length;i++) {
a[i] = random.nextInt(10);
System.out.print(a[i]+" ");
}
System.out.println("");
exchange(a, 0, a.length-1);
System.out.print("交换后数组:");
for(int i = 0,j = a.length;i < j;i++) {
System.out.print(a[i]+" ");
}
}
/**
*
* @param a 要排序的数组
* @param left 数组最左边的下标
* @param right 数组最右边的小标
*
* @author xiadekang
* @createDate 2018年7月30日
*/
public static void exchange(int []a, int left, int right) {
//退出条件
if(left>right) {
return;
}
int first = a[left];//基数
int i=left;
int j=right;
int middle = 0;//交换值的中介载体
while(i!=j){
//查找右边大于
while (first<=a[j] && j>i) {
j--;
}
//查找左边小于第一个值
while (first>=a[i] && j>i) {
i++;
}
//交换位置
middle = a[j];
a[j] = a[i];
a[i] = middle;
}
//交换基数位置
a[left] = a[j];
a[j] = first;
//处理左边
exchange(a, left, j-1);
//处理右边
exchange(a, j+1, right);
}
}
优化:当遇到1,2,4,6,7,7,8,6,4这样的数组时,如果还是取第一个下标值为1的数为基数,那么效率明显会很低。这时如何取一个合理的基数就是优化的关键之处。有的优化方式通过随机从数组取三个数,然后取这三个数的中排在中间的数为基数,当然还有其他方式,这里就不一一阐述了。