小白初識 - 快速排序(QuickSort)
阿新 • • 發佈:2019-01-30
我們 quicksort 現在 ngx pre length ima 快速 排序。
我個人覺得快速排序和歸並排序有相似之處,都是用到了分治的思想,將大問題拆分成若幹個小問題。
不同的地方是歸並排序是先把大問題拆分好了之後再排序,而快速排序則是一邊拆分,一邊排序。
快速排序的原理就是,針對一個數組,我們任意選取數組中的一個數,將數組中的數與它一一比較,如果小於它呢,就放左邊,
大於它呢,就放右邊。再針對左邊和右邊的重復上述動作即可,所以也要用到遞歸。
先來看看遞歸公式:quickSort(p...r) = quickSort(p...q-1) + quickSort(q+1, r),我們一般選數組末尾的數作為用來比較的數。
再來看看對於一個數組的快速排序演示圖:
以下是我的Java代碼實現:
1 package com.structure.sort; 2 3 /** 4 * @author zhangxingrui 5 * @create 2019-01-27 22:52 6 **/ 7 public class QuickSort { 8 9 public static void main(String[] args) { 10 int[] numbers = {9, 1, 2, 8, 7, 3, 6, 4, 3, 5, 0, 9, 19, 39, 25, 34, 17, 24, 23, 34, 20};11 // int[] numbers = {3,1,2}; 12 // 快速排序借助遞歸來實現,重要的是要找到遞歸的終結條件(不然容易發生堆棧異常) 13 // 遞推公式:quickSort(p...r) = merge(p, q - 1) + merge(q+1, r) 14 // 終結條件:p >= r 15 quickSort(numbers, 0, numbers.length - 1); 16 for (int number : numbers) { 17 System.out.println(number);18 } 19 } 20 21 private static void quickSort(int[] numbers, int p, int r){ 22 if(p >= r) 23 return; 24 int q = partition(numbers, p, r); 25 quickSort(numbers, p, q - 1); 26 quickSort(numbers, q + 1, r); 27 } 28 29 /** 30 * @Author: xingrui 31 * @Description: 分區 32 * @Date: 23:13 2019/1/27 33 */ 34 private static int partition(int[] numbers, int p, int r){ 35 int k = numbers[r]; 36 int i = p; 37 38 for (int j = p; j <= r; ++j) { 39 if(numbers[j] < k){ 40 int temp = numbers[i]; 41 numbers[i] = numbers[j]; 42 numbers[j] = temp; 43 i++; 44 } 45 } 46 numbers[r] = numbers[i]; 47 numbers[i] = k; 48 return i; 49 } 50 51 }
其中的重點就是分區的函數是如何實現的,分區這裏實現用的其實是類似選擇排序的方式,將指定位置的兩個元素進行交換,
從而實現k的左邊都是小於k的,k的右邊都是大於k的。
最後我們來問三個問題:
1.快速排序是穩定的排序算法嗎?
2.快速排序是原地排序嗎?
3.快速排序的時間復雜度是多少?
解答:
1.快速排序不是穩定的排序算法,比如我們現在有一個數組[4, 10, 9, 8, 10, 7, 8],根據分區部分代碼的交換邏,第一個十會被交換到
第二個十的後邊兒,所以快排不是穩定的排序算法。
2.快排是原地排序。整個排序過程中沒有申請多余的內存空間。
3.快速排序的時間復雜度計算比較復雜,主要考慮兩種情況:
當每次分區都差不多可以從中間分區,那麽快排的時間復雜度計算方式與歸並排序的時間復雜度計算方式相仿,都是O(nlogn);
當每次分區都把兩邊分的很不平衡,比如分成9:1或者8:2,在這種極端情況下快排的時間復雜度會退化到O(n2)。
小白初識 - 快速排序(QuickSort)