一,算法思想:
要实现快速排序,一般策略是先随意的选取a[left]作为切分的基准元素,通俗来讲就是标志元素,
往后循环都和这个标志元素进行比较。然后我们循环从数组的右端开始往左端循环找寻小于切分元素的元素a[j],再从左
端向右端寻找大于切分元素的元素a[i],使此时的a[i]和a[j]交换,再重复进行找寻,交换。当i位置和j位置重合时,即左端指针和右端指针相遇时,
一轮寻找到此结束。此时,把切分元素填入i==j的位置(填坑法),基于切分元素实现数组一切为二。再递归调用左半边和右半边。当递归中发现left>=right
此时即为递归出口,元素已经全部有序。
二,代码:
/**
* 快速排序 不稳定
*平均情况O(nlog2n) 最好情况O(nlog2n) 最坏情况O(n*n) 辅助空间O(nlog2n)
**/
public class Qsort {
public static void main(String[] args) {
int[] a = {1, 2, 3, 5, 2, 0, 4, 9}; //测试数组
qso(a, 0, a.length - 1); //调用快速排序
for (int k : a) { //迭代输出数组
System.out.print(k+" ");
}
}
private static void qso(int a[], int left, int right) {
int i;
int j;
int t;
if (left >= right) return;//递归调用中,若left>=right,说明达到递归出口,元素已经全部有序
int temp = a[left];//定义a[left]为切分的基准元素(可优化为随机选取基准元素,消除数据依赖)
i = left;
j = right;
while (i != j) {
while (a[j] >= temp && i < j) j--;//从右往左找到需要交换的a[j]位置
while (a[i] <= temp && i < j) i++;//从左往右找到需要交换的a[i]位置
if (i < j) { // 满足i<j,交换a[i]和a[j]两个位置
t = a[i];
a[i] = a[j];
a[j] = t;
}
}//若跳出循环,证明i和j相遇
//此时,需要将基准数tem归位到i==j的那个位置
a[left] = a[i];
a[i] = temp;
//将已经归为的左边和右边的数,再次递归调用快速排序
qso(a,left,i-1);
qso(a,i+1,right);
}
}
三,优化策略
*可优化1 打乱数组,达到随机选择基准元素的作用
*可优化2 判断长度,当数组长度较小时,直接调用插入排序算法,效率更高
*可优化3 三取样切分等