數據結構之快速排序(三)

快速排序是冒泡排序的改進版,也是最好的一種內排序,快速排序思想—-分治法也確實實用,因此很多軟件公司的筆試面試,包括像騰訊,微軟等知名IT公司都喜歡考這個,還有大大小的程序方面的考試如軟考,考研中也常常出現快速排序的身影。也是作爲程序員必須掌握的一種排序方法。

思想:1.在待排序的元素任取一個元素作爲基準(通常選第一個元素,但最好的選擇方法是從待排序元素中隨機選取一個作爲基準),稱爲基準元素;
2.將待排序的元素進行分區,比基準元素大的元素放在它的右邊,比其小的放在它的左邊;
3.對左右兩個分區重複以上步驟直到所有元素都是有序的。
所以我是把快速排序聯想成東拆西補或左拆右補,一邊拆一邊補,直到所有元素達到有序狀態。也有人稱之爲 挖坑(拆)填數(補)+分治法(基準 元素的 左側 和右側 分別按照 左拆右補的方法)

圖解:
這裏寫圖片描述

初步實現:

public int quickSort(int arr[], int _left, int _right) {

        int baseTemp = arr[_left];//  基準元素
        while (_left < _right) {

            // 從右向左  開始置換     拆右補左
            while (_right > _left && arr[_right] >= baseTemp) _right--;
            if (_left < _right) arr[_left++] = arr[_right];

            // 從左向右  開始置換  拆左補右
            while (_left < _right && arr[_left] <= baseTemp) _left++;
            if (_left < _right) arr[_right--] = arr[_left];

        }

        //退出時,_left等於_rigth。將baseTemp填到這個坑中。基準元素歸位
        arr[_left] = baseTemp;
        return _left;
    }

    //  分治法  基準元素的左側  和  基準元素的右側
    public void quickSortRecursion(int arr[], int _left, int _right) {
        int base = quickSort(arr, _left, _right);
        if (_left < _right) {
            //  對 基準元素的  左側 進行  遞歸排序
            quickSortRecursion(arr, _left, base - 1);
            quickSortRecursion(arr, base + 1, _right);
        }
    }

精簡優化代碼:

 public static void quickSortBetter(int arr[], int _left, int _right) {
        int left = _left;
        int right = _right;
        if (left < right) {   //待排序的元素至少有兩個的情況
            int temp = arr[left];  //待排序的第一個元素作爲基準元素
            while (left < right) {   //從左右兩邊交替掃描,直到left = right

                while (right > left && arr[right] >= temp)
                    right--;        //從右往左掃描,找到第一個比基準元素小的元素
                arr[left++] = arr[right];  //找到這種元素arr[right]後與arr[left]交換

                while (left < right && arr[left] <= temp)
                    left++;         //從左往右掃描,找到第一個比基準元素大的元素
                arr[right--] = arr[left];  //找到這種元素arr[left]後,與arr[right]交換

            }
            arr[left] = temp;    //基準元素歸位
            quickSortBetter(arr, _left, left - 1);  //對基準元素左邊的元素進行遞歸排序
            quickSortBetter(arr, right + 1, _right);  //對基準元素右邊的進行遞歸排序
        }
    }

算法分析:
1.當分區選取的基準元素爲待排序元素中的最大或最小值時,爲最壞的情況,時間複雜度和直接插入排序的一樣,移動次數達到最大值 Cmax = 1+2+…+(n-1) = n*(n-1)/2 = O(n^2) 此時最好時間複雜爲O(n^2)。
2.當分區選取的基準元素爲待排序元素中的”中值”,爲最好的情況,時間複雜度爲O(nlog2n)。
3.快速排序的空間複雜度爲O(log2n).
4.當待排序元素類似[6,1,3,7,3]且基準元素爲6時,經過分區,形成[1,3,3,6,7],兩個3的相對位置發生了改變,所是快速排序是一種不穩定排序。

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