快速排序(Quicksort)是對冒泡排序的一種改進。
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
時間複雜度
當數據有序時,以第一個關鍵字爲基準分爲兩個子序列,前一個子序列爲空,此時執行效率最差。
而當數據隨機分佈時,以第一個關鍵字爲基準分爲兩個子序列,兩個子序列的元素個數接近相等,此時執行效率最好。
所以,數據越隨機分佈時,快速排序性能越好;數據越接近有序,快速排序性能越差。
空間複雜度
快速排序在每次分割的過程中,需要 1 個空間存儲基準值。而快速排序的大概需要 NlogN次的分割處理,所以佔用空間也是 NlogN(底數爲2)個。
算法穩定性
在快速排序中,相等元素可能會因爲分區而交換順序,所以它是不穩定的算法。
荷蘭國旗問題引出
給定一個數組arr, 和一個數num, 請把小於num的數放在數組的左邊, 等於num的數放在數組的中間, 大於num的數放在數組的
右邊。
要求額外空間複雜度O(1),時間複雜度O(N)
實現算法:
假設num=arr[arr.length-1],即取數組最後一個值進行比較。left、right分別爲左右區域的指針。
如果當前值小於num,則將left指針向前移動一位,然後當前值與left區域新增的一位交換;
如果當前值大於num,則將right指針向後移動一位,然後將當前值與right區域新增的一位進行交換;
如果當前值等於num,不進行交換操作,繼續向下遍歷;
if arr[index] < num:
left++; swap(arr[index], arr[left]);
if arr[index] > num:
right--; swap(arr[index], arr[right]);
else
index++;
快排:將一個數組分成小於某值和大於某值的前後兩部分,再對前後兩部分分別使用快排。(分治思想)。
java代碼實現:
package quickSort;
import java.util.Arrays;
import java.util.Random;
/**
* @ClassName QuickSortDemo
* @Description TODO
* @Author
* @Date 19-7-17 上午10:20
**/
public class QuickSortDemo {
public static void quickSort(int[] nums, int L, int R) {
if (L < R) {
// swap(nums, (int) (L+(Math.random()*(R-L+1))), R); //此行代碼實現隨機快排
int [] p = partition(nums, L, R);
quickSort(nums, L, p[0] - 1);
quickSort(nums, p[1] + 1, R);
}
}
private static int[] partition(int[] nums, int L, int R) {
int left = L - 1;
int right = R;
while (L < right) {
if (nums[L] < nums[R]) {
swap(nums, ++left, L++);
} else if (nums[L] > nums[R]) {
swap(nums, --right, L);
}
else
L++;
}
swap(nums, right, R);
return new int[] {left + 1, right};
}
private static void swap(int[] nums, int i, int i1) {
int tmp = nums[i];
nums[i] = nums[i1];
nums[i1] = tmp;
}
public static void main(String[] args) {
Random random = new Random();
int[] data = new int[20];
for (int i = 0; i < data.length; i++) {
data[i] = random.nextInt(100);
}
System.out.println(Arrays.toString(data));
System.out.println("************ quick sort: ***********");
quickSort(data, 0, data.length - 1);
System.out.println(Arrays.toString(data));
}
}
經典快排是每次選擇最後一位進行比較,受數據分佈影響較大,隨機快排每次隨機選擇一位來進行比較,平均效率更高。