快速排序比前面几种稍微难理解一些,但是明白了运行原理还是很简单的。
定义
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
就是寻找一个基准值,比基准值大的放到右边,基准值小的放到左边。
图解过程
首先是无序的数组,这里定义low从第一个开始,high为数组的最后一个。这时候再定义一个基准值。
第一步从数组的末尾开始,判断如果最大值是大于基准值的话,high就减1;如果小于基准值就将high的值赋值给low(图中10 < 11,所以将值赋值到low的位置)
下一步,从前往后进行排序,如果当前值小于基准值,那么low就加1;如果当前值大于基准值(图中56 > 11),就将low的值赋值给high。
下一步就是继续从末尾往前,此时发现上图中的6 < 11,所以将high的值赋值给low。
然后再从前往后,知道low==high的时候,此时的位置就是基准值的位置。
这样一整个流程下来,就特别清楚,快速排序就是将比基准值大的放在右边,比基准值小的放在左边。
后面只要进行递归操作,分别对前半部分和后半部分排序,就能变成有序数组了。
代码实现
package com.sdf.lib;
import java.util.Arrays;
public class MyClass {
public static void main(String args[]) {
System.out.println("hello world!");
int[] array = {11,56,6,10};
quickSort(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] data, int low, int high) {
if(data == null || data.length <= 1) {
return;
}
if(low < high) {
int index = getIndex(data, low, high);
quickSort(data, low, index - 1);
quickSort(data, index + 1, high);
}
}
public static int getIndex(int[] data, int low, int high) {
//定义基准值,这里的选取取第一个
int tmp = data[low];
while (low < high) {
//从末尾开始,如果当前值大于或等于基准值,high就减1
while(low < high && data[high] >= tmp){
high --;
}
//当前值小于基准值,将high对应的值赋值给low
data[low] = data[high];
//从数组开头开始,如果当前值小于或等于基准值,low就加1
while(low < high && data[low] <= tmp){
low++;
}
//当前值大于基准值,就将low对应的值赋值给high
data[high] = data[low];
}
// 跳出循环此时low和high相等,此时的low或high就是基准值的正确索引位置
// 由原理部分可以很清楚的知道low(high)位置的值并不是基准值,所以需要将基准值赋值给arr[low](arr[high])
data[low] = tmp;
return low;
}
}
结果
[6, 10, 11, 56]
小结
快速排序的原理即和基准值比较,将大于或者小于的数分别放在两边,达到排序的效果。快排的性能在所有排序算法里面是最好的,数据规模越大快速排序的性能越优。
快速排序的平均时间复杂度和最坏时间复杂度分别是O(nlgn)、O(n^2)。
当排序成为基本有序状态时,快速排序退化为O(n^2),一般情况下排序为指数复杂度。
快排在极端情况下会退化成 O(n^{2}) 的算法,因此假如在提前得知处理数据可能会出现极端情况的前提下,可以选择使用较为稳定的归并排序。