排序算法之快速排序(Java實現)


一、介紹及原理

​ 簡單來說,快速排序就是每次選擇一個基准。在遍歷整個數組的過程中,將比基准小的數放到左側,比基准大的數放到右側。這樣在一次循環過后,雖然整體依然無序,但是算法將數列分為兩部分:左側部分小於基准數而右側部分大於基准數。之后利用分治思想分別將左側部分與右側部分進行快排,最終則可以得到一個完全有序的數組。

二、代碼實現

 public static void QuickSort(int[] arr , int left , int right) {
     // 遞歸的出口必須仔細考慮清楚,否則就會陷入無窮循環從而使棧溢出   
     if (left >= right) {
            return;
        }
        int pivot = arr[left];
        int i = left;
        int j = right;
        while (i < j) {
            // 這里如果pivot 選在左側,就要先從右側開始遍歷,反之則先從左側開始
            while (arr[j] > pivot && i < j) {
                j--;
            }
            // 找到比基准小的數換到左側去
            arr[i] = arr[j];
            while (arr[i] < pivot && i < j) {
                i++;
            }
            // 找到比基准大的數換到右側去
            arr[j] = arr[i];
        }
        // 最后將基准放到中間位置
        arr[i] = pivot;
        //  遞歸快排左側數列
        QuickSort(arr,left,i - 1);
        // 遞歸遍歷右側數列
        QuickSort(arr, i + 1, right);
    }

三、時間復雜度

在算法中有一個主定理可用來考慮算法的時間復雜度:

\[T(n) = aT(\frac{n}{b}) + O(n^{d}),(a>1,b>1,d>0) \]

\[if \ \ d <log_{b}^{a}:T(n) = O(n^{log_{b}^{a}}) \\ if \ \ d =log_{b}^{a}:T(n) = O(n^{log_{b}^{a}}log_{n}) \\ if \ \ d >log_{b}^{a}:T(n) = O(n^{d}) \]

在快速排序這個問題中:

\[T(n) = 2T(\frac{n}{2}) + O(n) \ = 4T(\frac{n}{4}) + O(n) + O(n) \]

仔細考慮排序過程,第一次將數組整個掃描了一遍,時間復雜度為O(n),掃描之后將數組分成了兩個子問題:之后兩個問題分為四個子問題,時間復雜度又用了O(n),正好符合上式。

其中,O(n) 是每一次分區所用的時間復雜度,將參數帶入可知,快速排序的時間復雜度為O(nLogn)。

其實不利用公式來考慮時間復雜度的話:每次用O(n) 的時間復雜度將問題為了兩個子問題。假設m 次過后子問題划分為1 ,那么有

\[n/2/2/.../2 = \frac{n}{2^{m}} = 1 \]

所以經過了m次迭代后,問題歸一。每次的時間復雜度為O(n) = cn,那么可得快速排序的時間復雜度為:

\[cmn = clog_{2}{n}n = O(nlogn) \]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM