基礎算法-快速排序的理解與實現-Android版

快速排序:冒泡的進化版,根據某一值key, 將大於key 的往後放,將小於key的往前放;通俗結果就是最後key值左邊的比key都小,key值右邊的比key都大;在對兩側的序列單獨進行key值比較交換,依次類推...

代碼的實現與理解:

         int a[] = {5, 3, 4, 8, 9, 1, 7, 0, 2, 6};
         sort(a, 0, a.length - 1);
         for (int h = 0; h < a.length; h++) {
             Log.i("chy1234", "==結果數據===" + a[h]);
         }

/*********************************************************************/
   private void sort(int a[], int leftBound, int rightBound) {
        if (leftBound >= rightBound) {
            // 如果左節點 >= 右節點, 說明此次遍歷結束
            return;
        }
        // 獲取第一輪快排後的key 的位置
        int mid =  partition(a, leftBound, rightBound);
        // 針對前半段進行快速排序
        sort(a, leftBound, mid-1);
        // 針對後半段進行快速排序
        sort (a, mid +1, rightBound);
    }

/********************************************************************/
 /**
     * 快排處理
     * 
     * @param a
     * @param leftBound
     * @param rightBound
     * @return   返回排完之後key的位置
     */
    private int partition(int a[], int leftBound, int rightBound) {

        int pivot = a[leftBound];    // 設定key值爲左邊第一個值
        int left = leftBound + 1;    // 從左邊第二個位置開始
        int right = rightBound;      // 尾結點
        /**
         * 循環結束點===>當左節點大於等於右節點則結束循環
         *
         * 關於 left = right  情況的解釋:(本人對於這個比較迷惑,所以記錄一下)
         *  當存在數列中僅有兩個數比較時,例如leftBound  = 0, rightBound = 1 ;
         *  會出現上面的 left = right;
         *  例如(5, 3)比較, left  = 1, right = 1;
         *  不會進入循環,最後與key值交換時,出現的的是 5 和 5 交換,(5, 3)不符合預期效果
         *  所以此處循環應該有left = right的情況; 這樣以 5 爲基準, 
         *  則left在進入循環後會變成 left = 2;right = 1;
         *  這樣在最後的 key 值位置校正時,就是 5 與 3 進行交換了,符號預期效果
         *
         */
        while (left <= right) {
            /**
             * 先從左邊開始遍歷數組,找到第一個大於pivot的值,
             *  如果有那麼此時值爲 a[left]
             *
             *  循環條件: 左節點不能大於右節點 並且 值要比 pivot 小的,
             *          纔可以繼續循環;直到遇到left > right 情況或者
             *          a[left] > pivot的情況,則循環終止
             */
            while (left <= right && a[left] <= pivot) left++;

            /**
             * 從右邊邊開始遍歷數組,找到第一個小於 pivot 的值,
             *  如果有那麼此時值爲 a[right]
             *
             *  循環條件: 左節點不能大於右節點 並且 值要比 pivot大的,
             *          纔可以繼續循環;直到遇到left > right 情況或者
             *          a[right] < pivot的情況,則循環終止
             */
            while (left <= right && a[right] >= pivot) right--;

            /**
             * 如果跳出以上循環的條件不是因爲節點關係,那麼默認找到了一組最大值和最小值
             *  此時需要交換最大值和最小值的位置,以便完成大的放後邊,小的放前面的規則
             *   如果滿足交換條件 left < right 則可知 a[left] > key; a[right] < key
             */
            if (left < right) {
                int temp = a[left];
                a[left] = a[right];
                a[right] = temp;

            }



        }
        /**
         * 校正 key 的位置
         *
         * 等待循環結束後,除卻第一個值(第一個值被認作key值)
         * 後面的數列以某一節點爲分界點,分界點前面的都小於key,
         * 分界點後邊的都大於key;
         *  此時需要矯正 key 的位置,把他放到分界點上
         *  =====分界點的位置在哪裏呢?====-----此處代碼針對分界點我們依賴於left的位置--------
         *  上面外層循環結束的條件是 left > right && a[left] > pivot
         *  所以 left 本身的位置應該是(以key爲分界點)數列右半部分的第一個值
         *  因爲這裏處理的是key 與 首位進行交換, 所以取 a[left - 1]爲 key 的位置
         */
        int temp = a[leftBound];
        a[leftBound] = a[left - 1];
        a[left - 1] = temp;

        return  left -1;
    }

快速排序:

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