快速排序就這麼簡單

快速排序就這麼簡單

從前面已經講解了冒泡排序、選擇排序、插入排序了,本章主要講解的是快速排序,但願你們看完可以理解並手寫出快速排序的代碼,而後就經過面試了!若是我寫得有錯誤的地方也請你們在評論下指出。html

快速排序的介紹

來源百度百科:面試

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。數組

快速排序是面試出現的可能性比較高的,也是常常會用到的一種排序,應該重點掌握。微信

前面一個章節已經講了遞歸了,那麼如今來看快速排序就很是簡單了。優化

1、第一趟快速排序

經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小ui

百度百科的話並無說到重點,更簡單的理解是這樣的:在數組中找一個支點(任意),通過一趟排序後,支點左邊的數都要比支點小,支點右邊的數都要比支點大!spa

如今咱們有一個數組:int arr[]={1,4,5,67,2,7,8,6,9,44};code

通過一趟排序以後,若是我選擇數組中間的數做爲支點:7(任意的),那麼第一趟排序後的結果是這樣的:{1,4,5,6,2,7,8,67,9,44}htm

那麼就實現了支點左邊的數比支點小,支點右邊的數比支點大blog

2、遞歸分析與代碼實現

如今咱們的數組是這樣的:{1,4,5,6,2,7,8,67,9,44},既然咱們比7小的在左邊,比7大的在右邊,那麼咱們只要將」左邊「的排好順序,又將」右邊「的排好序,那整個數組是否是就有序了?想想,是否是?

又回顧一下遞歸:」左邊「的排好順序,」右邊「的排好序,跟咱們第一趟排序的作法是否是一致的?

只不過是參數不同:第一趟排序是任選了一個支點,比支點小的在左邊,比支點大的在右邊。那麼,咱們想要」左邊「的排好順序,只要在」左邊「部分找一個支點,比支點小的在左邊,比支點大的在右邊。

..............

在數組中使用遞歸依照個人慣性,每每定義兩個變量:LRL指向第一個數組元素,R指向在最後一個數組元素

遞歸出口也很容易找到:若是數組只有一個元素時,那麼就不用排序了

因此,咱們能夠寫出這樣的代碼:

public static void main(String[] args) {
        int[] arr = {1, 4, 5, 67, 2, 7, 8, 6, 9, 44};

        quickSort(arr, 0, 9);

        System.out.println("Java3y   " + arr);


    }

    /**
     * 快速排序
     *
     * @param arr
     * @param L   指向數組第一個元素
     * @param R   指向數組最後一個元素
     */
    public static void quickSort(int[] arr, int L, int R) {
        int i = L;
        int j = R;

        //支點
        int pivot = arr[(L + R) / 2];

        //左右兩端進行掃描,只要兩端尚未交替,就一直掃描
        while (i <= j) {

            //尋找直到比支點大的數
            while (pivot > arr[i])
                i++;

            //尋找直到比支點小的數
            while (pivot < arr[j])
                j--;

            //此時已經分別找到了比支點小的數(右邊)、比支點大的數(左邊),它們進行交換
            if (i <= j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
                j--;
            }
        }
        //上面一個while保證了第一趟排序支點的左邊比支點小,支點的右邊比支點大了。


        //「左邊」再作排序,直到左邊剩下一個數(遞歸出口)
        if (L < j)
            quickSort(arr, L, j);

        //「右邊」再作排序,直到右邊剩下一個數(遞歸出口)
        if (i < R)
            quickSort(arr, i, R);
    }

 

 

3、快速排序優化

來源:www.cnblogs.com/noKing/arch…

我這裏簡單歸納一下思路,有興趣的同窗可到上面的連接上閱讀:

  • 隨機選取基準值base(支點隨機選取)
  • 配合着使用插入排序(當問題規模較小時,近乎有序時,插入排序表現的很好)
  • 當大量數據,且重複數多時,用三路快排

4、擴展閱讀

原理都是同樣的,在細節上有些變化而已

  • 它是交換完畢後記錄支點的角標,而後再劈開兩半進行遞歸調用

C語言代碼實現:

void QuickSort ( int*arr,int low, int high);
        int FindPos ( int*arr,int low, int high);


        int FindPos ( int*arr,int low, int high)
        {
            int val = arr[low];

            while (low < high) {
                while (low < high && arr[high] >= val)
                    --high;
                arr[low] = arr[high];
                while (low < high && arr[low] <= val)
                    ++low;
                arr[high] = arr[low];
            }
            arr[low] = val;
            return low;
        }


        void QuickSort ( int arr[], int low, int high)
        {
            int pos;
            if (low < high) {
                pos = FindPos(arr, low, high);
                QuickSort(arr, low, pos - 1);//劈兩半,左邊 
                QuickSort(arr, pos + 1, high); //右邊 
            }
            return;
        }

        int main ()
        {
            int arr[ 6]={ 5, 3, -88, 77, 44, -1 } ;
            int i;
            QuickSort(arr, 0, 5);
            for (i = 0; i < 6; i++)
                printf("%d   ", arr[i]);
            printf("\n");
            return 0;
        }

若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y

相關文章
相關標籤/搜索