O(nlogn)排序之归快速排序
1. 原理
归并排序是不分任何情况直接将数组一分为二。而快速排序是将数组分为一组元素全部小于一个元素v,另一组元素,全部大于这一个元素v。
排序的时候通常是以第一个元素为基石,来进行递归排序。
package com.fgy.learn;
/**
* Created by snow_fgy on 2019/4/6.
*/
public class QuickSort1 {
//获取随机数组
public int[] getReadom(int n, int random) {
int [] a = new int[n];
for (int i = 0; i < n; i++){
a[i] = (int) (Math.random() * random);
}
return a;
}
public void quickSort(int [] arr) {
quickInnerSort(arr, 0, arr.length - 1);
for (int i: arr) {
System.out.print(i + " ");
}
System.out.println();
}
//将arr[l.....r]部分进行快速排序
public void quickInnerSort(int [] arr, int l, int r) {
if (l >= r) {
return;
}
int p = partition(arr, l, r);
quickInnerSort(arr, l, p - 1);
quickInnerSort(arr, p+1, r);
}
//将arr[l...r]进行一次partition操作
//返回一个p值,满足:arr[l....p-1] < arr[p], arr[p+1 ... r] > arr[p]
private int partition(int[] arr, int l, int r) {
//优化:
int radomIndex = (int) Math.random() * (r - l + 1) + l;
int temp1 = arr[l];
arr[l] = arr[radomIndex];
arr[radomIndex] = temp1;
//以第一个元素为基石
int v = arr[l];
//arr[l+1...j] < v, arr[j+1...r) > v
int j = l;
for (int i = l+1; i <= r; i++) {
if (arr[i] < v) {
//进行一次交换操作
int temp = arr[j+1];
arr[j+1] = arr[i];
arr[i] = temp;
j++;
}
}
//将基石移到该在的位置
arr[l] = arr[j];
arr[j] = v;
return j;
}
public static void main(String[] args) {
QuickSort1 sort = new QuickSort1();
int[] arr = sort.getReadom(1000 , 10000);
long time1 = System.currentTimeMillis();
sort.quickSort(arr);
long time2 = System.currentTimeMillis();
System.out.println("selectionSort: " + (time2 - time1) / 1000.0 + "s");
}
}
优化
1.高级的排序算法到底层的时候,用插入排序
2.快排最差的情况是,O(n^2)。随机选择基石,而不是最左侧元素。随机选择数组中的元素,然后和最左侧位置元素交换值。
双路快排:
private int partition2(int[] arr, int l, int r) {
int radomIndex = (int) Math.random() * (r - l + 1) + l;
int temp1 = arr[l];
arr[l] = arr[radomIndex];
arr[radomIndex] = temp1;
//以第一个元素为基石
int v = arr[l];
int i = l+1;
int j = r;
while (true){
while (i <= r && arr[i] < v) {
i++;
}
while (j >= l+1 && arr[j] > v) {
j--;
}
if (i >= j) {
break;
}
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
i++;
j--;
}
//将基石移到该在的位置
arr[l] = arr[j];
arr[j] = v;
return j;
}
三路快速排序
private void quickInnerSort3(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int radomIndex = (int) Math.random() * (r - l + 1) + l;
int temp1 = arr[l];
arr[l] = arr[radomIndex];
arr[radomIndex] = temp1;
//以第一个元素为基石
int v = arr[l];
int lt = l;
int gt = r + 1;
int i = l+1;
while (i < gt) {
if (arr[i] < v) {
int temp = arr[i];
arr[i] = arr[lt+1];
arr[lt+1] = temp;
lt++;
i++;
} else if (arr[i] > v){
int temp = arr[i];
arr[i] = arr[gt-1];
arr[gt-1] = temp;
gt--;
} else {
i++;
}
}
arr[l] = arr[lt];
arr[lt] = v;
quickInnerSort3(arr, l, lt-1);
quickInnerSort3(arr, gt, r);
}```