1. 程式人生 > >排序演算法-快排

排序演算法-快排

    今天聊聊排序演算法,排序演算法平時也會用到,有很多比如,冒泡,快排,選擇,歸併排序等.今天就聊一聊快速排序演算法排序演算法的一個宗旨就是經過一趟排序,何為一趟排序呢?就是遍歷完一次陣列,陣列中的一部分資料比另外一部分的資料都要小.當然這兩部分資料內部仍然是無序的,然後我們再對這兩部分資料分別進行排序,如此遞迴下去.所以整個演算法的核心思想就是這樣,今天介紹兩種實現快速排序的方法,一種是交換排序以及另一種方法(這種我也叫不出來方法),大家看程式碼就能看明白.

    首先看第一種方法,

void quickSort1(vector<int> &nums, int left, int right){
    if (left<right){
        int key = nums[left], low = left+1, high = right;
        while (low<=high){   //為什麼是<=
            while (low<high && nums[low]>key && nums[high]<key)
                swap(nums[low++], nums[high--]);
            if (nums[low]<=key) low++;
            if (nums[high]>=key) high--;
        }
        swap(nums[left], nums[high]); //為什麼是和high位置交換
        quickSort1(nums, left, high-1);
        quickSort1(nums, high+1, right);
    }
}
    因為演算法是從兩個端點向中間收縮,所以我們要確保left<right,首先我們選取一個key值,等完成一趟排序之後,key左邊的元素統統小於key右邊的元素,然後再從key處割裂開,左右兩邊分別進行以上演算法.然後定義low為左邊的起始點,high為右邊的起始點.如果滿足第一個while條件,就相當於左邊的數值大,右邊的數值小,然後我們交換一下兩者,同時把low和high接著往中間走一步,再繼續比較.當不符合條件時,我們跳出當前while迴圈,然後執行下面兩個判斷,這兩個判斷的目的是為了防止產生死迴圈,如果沒有這兩句話,當nums[low]=key或者當nums[high]==key時,不符合上面的while迴圈,是不是就陷入了死迴圈.當退出while迴圈時,high<=low而且nums[low]>key,而且這一個過程中key值一直沒動,我們需要把他放在合適的位置,此時nums[low]>key,那key還能和low位置的值交換嗎?好像不可以了,那為什麼和high位置的值交換呢,如果我們在第一個迴圈中設定low<high,那麼high的最小值就是low,所以也不能和high位置的值交換,那如果我們設定為low<=high時,結束while迴圈時high位置就在low-1處,所以key和這個位置的值交換.這樣就完成了一趟遍歷,接下來,就從high處把陣列割裂開,然後對兩段陣列分別排序即可.

    第二種方法:程式碼如下

void quickSort2(vector<int> &v, int left, int right){
    if (left < right){
        int key = v[left], low = left, high = right;
        while (low < high){
            while (low < high && v[high] >= key)
                high--;
            if (low < high)
                v[low++] = v[high];
            while (low < high && v[low] <= key)
                low++;
            if (low < high)
                v[high--] = v[low];
        }
        v[low] = key;
        quickSort2(v, left, low-1);
        quickSort2(v, low+1, right);
    }
}
        這種方法就比較好理解了,先從右邊遍歷陣列,直到遇到一個比key值小的,然後把這個值放到low位置處,low指向下一個位置,這時陣列中有兩個v[high]了,在low位置處(前面)的這個是正確的位置,在high處這個位置是不正確的位置.然後從左邊開始向右遍歷,直到遇到一個比key值大的數值,然後把他放到右邊的high位置處,這時是不是陣列中有了兩個v[low]了,前面這個位置是不正確的,所以要把key值放到這個位置.接著從low處割裂開,然後對兩段陣列進行排序.