快速排序

算法思想:

快速排序採用了分治的思想,在對數組進行排序時,首先選取數組中的一個元素作爲基準元素,然後將數組中所有小於等於基準元素的元素放在基準元素的左邊,而大於基準元素的放在基準元素的右邊,然後對基準元素的左右兩邊的序列採用同樣的方式對其進行排序。

代碼實現思路:

在代碼實現中都是選擇第一個元素作爲基準元素。

思路1:在白話經典算法系列之六 快速排序 快速搞定中提出的是挖坑填數的方法,即首先用一個變量保存基準元素,此時基準元素的位置就是個,然後用一個指針循環的從數組最右往左找到第一個小於基準元素的元素,然後將這個元素填入坑中,同時這個元素的位置處產生一個,然年再從左往由用一個指針找到第一個大於基準元素的元素,填入坑中。循環往復,直到兩個指針相等,指向同一個位置()這個位置是個坑,然後將基準元素填入這個坑中。然後遞歸的對基準元素左右序列進行排序。

思路2:在算法 3:最常用的排序——快速排序中,實現和思路一不一樣,首先是用來個指針分別從左往右和從右往左找到第一個大於和小於基準元素的兩個元素,然後交換,重複上述操作,直到兩個指針指向同一個位置,然後交換這個位置的元素和基準元素。

優化方法:

方法1:對於小數組,使用插入排序,避免遞歸調用。例如,當if(hi <= lo + M)時,就可以轉到插入排序。
方法2:選擇一個更好的基準元素。如選取中位數,隨機選取基準元素。
方法3:如果數組中含有大量的重複元素,可以採用三向切分。將數組切分爲三部分,分別對應於小於、等於和大於切分元素的數組元素。代碼參考快速排序及其優化

時間複雜度:

最好和平均情況下,是O(nlogn);最壞情況下,是O(n2)。

空間複雜度:

遞歸造成的棧空間的使用。
最好情況,遞歸的深度爲log2n,其空間複雜度也就爲O(logn)。
最壞情況,需要進行n‐1遞歸調用,其空間複雜度爲O(n)。這種情況可以通過隨機選取基準元素避免。
平均情況,空間複雜度也爲O(logn)。

穩定性:

不穩定。
在基準元素和a[lt]交換時可能打亂穩定性。

代碼實現:

package sort;

/**
 * @作者:dhc
 * @創建時間:21:44 2018/8/13
 * @排序方法:快速排序
 * @時間複雜度:O(nlogn)
 * @空間複雜度:遞歸造成的棧空間的使用,最好情況,遞歸的深度爲log2n,其空間複雜度也就爲O(logn),最壞情況,需要進行n‐1遞歸調用,
 * 其空間複雜度爲O(n),平均情況,空間複雜度也爲O(logn)
 * @穩定性:不穩定(在基準元素和a[lt]交換時可能打亂穩定性)
 */
public class QuickSort {
    public static void quickSort(int[] nums,int l, int r){
            if(l < r){
                int base = nums[l];
                int lt = l;
                int rt = r;
                while (lt < rt){
                    //找到一個比基準數小的元素
                    while (lt < rt && nums[rt] >= base ){
                        rt--;
                    }
                    if(lt < rt){
                        nums[lt++] = nums[rt];
                    }
                    while (lt < rt && nums[lt] <= base){
                        lt++;
                    }
                    if(lt < rt){
                        nums[rt--] = nums[lt];
                    }
                }
                nums[lt] = base;
                quickSort(nums,l,lt - 1);
                quickSort(nums,lt + 1,r);
            }
    }
    //交換
    public static void quickSort1(int[] nums,int l, int r){
            if(l >= r){
                return;
            }
            int base = nums[l];
            int lt = l;
            int rt = r;
            while(lt < rt){
                while(lt < rt && nums[rt] >= base){
                    rt--;
                }
                while(lt < rt && nums[lt] <= base){
                    lt++;
                }
                if(lt < rt){
                    int tem = nums[rt];
                    nums[rt] = nums[lt];
                    nums[lt] = tem;
                }
                //在這裏之所有不用對lt和rt進行加減操作,是因爲上面交換後他們當前對應的元素肯定是小於和大於基準元素的。
            }
            nums[l] = nums[rt];
            nums[rt] = base;
            quickSort1(nums,l,rt-1);
            quickSort1(nums,rt+1,r);

    }

    public static void main(String[] args) {
        int[] nums = new int[]{2,3,4,1,5,6,5,1,32,2};
        quickSort(nums,0,nums.length-1);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }
    }
}

參考鏈接

維基百科
白話經典算法系列之六 快速排序 快速搞定
算法 3:最常用的排序——快速排序
排序–快速排序及其優化
快速排序及其優化

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