JAVA基本算法詳細圖解---快速排序

快速排序思路

以排序數組int numbers = {4,8,2,3,8,9,5,2,3,6,5,8,7,3,6} 爲例

整體思路:

典型的分治思想

1、分解

     以數組的第一個元素爲基準進行排序,大於基準元素的 放在右邊,小於基準元素的放在左邊,這樣就將數組分成了三部分

  •  左邊數組(小於等於基準數組)
  • 基準元素本身
  • 右邊數組(大於等於基準數組)

2、遞歸求解

  • 分別在第一步基礎上 遞歸地對左邊數組以及右邊數組排序

3、合併

  •  就是將數組合並,由於第一步的所有左邊的數組元素 <= 基準元素 <=右邊數組,所以不需要進行任何額外的計算數組元素,合併後的數組就是有序的。

快速排序與歸併排序的不同點也在此處:

快速排序的排序操作發生在第一步分解時;

歸併排序的排序操作發生在第三部合併時;關於歸併排序大家可以看看之前的文章。

上面是整體的思路,我們也可以感受到上述三個步驟最困難的就是第一步,我們如何將數組劃分爲三份,這個比較不好理解,下面我用圖的方式來敘述:

下面請看詳細的圖解:

導出個excel還給我弄個"非會員水印",我窮我忍了。。。

下面咱們擼一下代碼

  
      /**
     * 快排  遞歸寫法
     * @param arr 排序數組
     * @param left 起始腳標
     * @param right 結束腳標
     * @return 結果
     */
    public static int[] quickSort(int[] arr,int left,int right){
        
        if(left < right){
            //第一步 分解
            int mid = partition(arr,left,right);
            //第二步 遞歸求解
            quickSort(arr,left,mid-1);
            quickSort(arr,mid+1,right);
            //第三步  不需要合併 因爲數組本身已經有序
        }
        return arr;
    }
    
    /**
     * 分解 將數組 分爲三份  對應上圖中的步驟
     */
    public static int partition(int[] arr,int left,int right){
        
        int i = left;
        int j = right+1;
        
        //選出一個基準值
        int mid = arr[left];
        while (true){
            //從右向左 找尋比mid小的位置
            while (mid < arr[--j] && j >= left );
            //從左向右找到比mid大的位置
            while (mid > arr[++i] && i < right );
            if(i >= j){
                break;
            }
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        arr[left] = arr[j];
        arr[j] = mid;
        return j;
    }

時間複雜度    T(n) = O(nlogn)。

就地快速排序使用的空間是  O(1)  的 ,是在原數組中排序

而真正消耗空間的就是遞歸調用了,因爲每次遞歸就要保持一些數據;

     最優的情況下空間複雜度爲:O(logn)  ;每一次都平分數組的情況

     最差的情況下空間複雜度爲:O( n )      ;退化爲冒泡排序的情況

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章