原理:(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据放到数组右边,小于分界值的数据放到数组的左边,此时左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序,对于左侧数据数组,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义,通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了。
时间复杂度:
最好:O(nlongn)
最坏:O(n^2)
平均:O(nlongn)
Java代码实现(附测试案例):
package day02;
public class Quick {
private static Comparable[] assist;
//比较v元素是否小于w元素
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w)<0;
}
//数组元素i和j交换位置
private static void exch(Comparable[] a, int i, int j) {
Comparable t=a[i];
a[i]=a[j];
a[j]=t;
}
//对数组内的元素进行排序
public static void sort(Comparable[] a) {
int lo=0;
int hi=a.length-1;
sort(a,lo,hi);
}
//对数组a中从索引lo到索引hi之间的元素进行排序
private static void sort(Comparable[] a, int lo, int hi) {
//安全性校验
if (hi <= lo) {
return;
}
//需要对数组中lo索引到hi索引处的元素进行分组
int partition=partition(a,lo,hi);//返回的是分组的分界值所在的索引,分界值位置变换后的索引
sort(a,lo,partition-1);//让左子组有序
sort(a, partition + 1, hi);//让由子组有序
}
public static int partition(Comparable[] a, int lo, int hi) {
//确定分界值
Comparable key=a[lo];
//定义两个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置
int left=lo;
int right=hi+1;
//切分
while (true) {
//先从右往左扫描,移动right指针,找到一个比分界值小的元素,停止
while (less(key, a[--right])) {
if (left == hi) {
break;
}
}
//判断left>=right,如果是,则证明元素扫描完毕,结束循环,如果不是,则交换元素即可
if (left >= right) {
break;
} else {
exch(a,left,right);
}
}
//交换分界值
exch(a,lo,right);
return right;
}
}
package test;
import day02.Quick;
import java.util.Arrays;
public class QuickTest {
public static void main(String[] args) {
Integer[] a = {6, 1, 2, 7, 9, 3, 4, 5, 8};
Quick.sort(a);
System.out.println(Arrays.toString(a));
}
}