天天看點

圖解排序算法(五)之快速排序——三數取中法

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序将要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分别進行快速排序,整個排序過程可以​​遞歸​​進行,以此達到整個資料變成有序​​序列​​

基本步驟

三數取中

  在快排的過程中,每一次我們要取一個元素作為樞紐值,以這個數字來将序列劃分為兩部分。在此我們采用三數取中法,也就是取左端、中間、右端三個數,然後進行排序,将中間數作為樞紐值。

圖解排序算法(五)之快速排序——三數取中法

 根據樞紐值進行分割

圖解排序算法(五)之快速排序——三數取中法
圖解排序算法(五)之快速排序——三數取中法

 

代碼實作

package sortdemo;

import java.util.Arrays;

/**
 * Created by chengxiao on 2016/12/14.
 * 快速排序
 */
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
        quickSort(arr, 0, arr.length - 1);
        System.out.println("排序結果:" + Arrays.toString(arr));
    }

    /**
     * @param arr
     * @param left  左指針
     * @param right 右指針
     */
    public static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            //擷取樞紐值,并将其放在目前待處理序列末尾
            dealPivot(arr, left, right);
            //樞紐值被放在序列末尾
            int pivot = right - 1;
            //左指針
            int i = left;
            //右指針
            int j = right - 1;
            while (true) {
                while (arr[++i] < arr[pivot]) {
                }
                while (j > left && arr[--j] > arr[pivot]) {
                }
                if (i < j) {
                    swap(arr, i, j);
                } else {
                    break;
                }
            }
            if (i < right) {
                swap(arr, i, right - 1);
            }
            quickSort(arr, left, i - 1);
            quickSort(arr, i + 1, right);
        }

    }

    /**
     * 處理樞紐值
     *
     * @param arr
     * @param left
     * @param right
     */
    public static void dealPivot(int[] arr, int left, int right) {
        int mid = (left + right) / 2;
        if (arr[left] > arr[mid]) {
            swap(arr, left, mid);
        }
        if (arr[left] > arr[right]) {
            swap(arr, left, right);
        }
        if (arr[right] < arr[mid]) {
            swap(arr, right, mid);
        }
        swap(arr, right - 1, mid);
    }

    /**
     * 交換元素通用處理
     *
     * @param arr
     * @param a
     * @param b
     */
    private static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}      

排序結果

排序結果:[1, 2, 3, 4, 5, 6, 7, 8]      

總結

  快速排序是一種交換類的排序,它同樣是分治法的經典展現。在一趟排序中将待排序的序列分割成兩組,其中一部分記錄的關鍵字均小于另一部分。然後分别對這兩組繼續進行排序,以使整個序列有序。在分割的過程中,樞紐值的選擇至關重要,本文采取了三位取中法,可以很大程度上避免分組"一邊倒"的情況。快速排序平均時間複雜度也為O(nlogn)級。

繼續閱讀