0.經典快排:將數組最后位置的數值x作為划分值,將小於等於x的放在左邊,大於x的放在右邊,
讓小於等於x區域的最后一個位置上放x值,如果有多個值等於x,中間區域放的什么值無所謂,左邊區域最后一個數放x就可以,左邊區域放小於等於x的值,右邊放大於x的值,經典快排的時間復雜度和數據狀況是有關系的。最好的時間復雜度是O(NlogN),最差情況的時間復雜度是O(N^2)
1.可以用荷蘭國旗問題來改進快速排序
(1)將小於x的放在左邊,等於x的放中間,大於x的放在右邊,這樣的話等於x的區域就不用動了,將小於x的區域和大於x的區域繼續這樣的過程進行遞歸操作,最終讓其整體有序。將原始區域清晰一些,每次搞定一個位置上的數,只搞定一個位置上的數。下次進行遞歸的時候是另外的兩個區域。
2.時間復雜度O(N*logN),額外空間復雜度O(logN),數據變化到一定狀況的時候,時間復雜度會變成O(N^2)的算法。
3.隨機快排。在整個數組中,每次不是把最后一個數拿來划分,隨機選一個數和最后位置上的數進行交換,然后拿隨機的數來進行划分。 這種情況下的時間復雜度只能用長期期望的方式來進行計算,長期期望的時間復雜度是O(NlogN)。隨機快排是最常用的排序。使用斷點長期的空間復雜度時候O(logN)。大樣本的情況下,長期期望是O(NlogN),空間復雜度是O(logN)。
4.代碼:
import java.util.Arrays;
public class QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
public static void quickSort(int[] arr, int l, int r) {
if (l < r) {
swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
int[] p = partition(arr, l, r);
quickSort(arr, l, p[0] - 1);
quickSort(arr, p[1] + 1, r);
}
}
public static int[] partition(int[] arr, int l, int r) {
int less = l - 1;
int more = r;
while (l < more) {
if (arr[l] < arr[r]) {
swap(arr, ++less, l++);
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);
} else {
l++;
}
}
swap(arr, more, r);
return new int[] { less + 1, more };
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
quickSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
quickSort(arr);
printArray(arr);
}
}